1
0
Fork 0
forked from fte/fteqw

prepare for proper binary auth instead of depending upon tls certs (using sha2(512) to ensure no modification). probably buggy on windows so not fully enabled yet.

allow for binary updates on linux as on windows (-allowupdate for modified/nonsvn builds).
dlightmask is now size_t, because we might as well allow that on 64bit cpus, this allows for 64 lightmaphack lights instead of 32.
fix potential openal issue with source=0.
added q3bsp_ignorestyles cvar to ignore rbsp styles (and reduce needed batch counts), should only be used on maps with subtle lighting changes (ones that are properly lit without toggling any lightswitches).
add support for directly loading foo.bsp.gz
Added prints to clarify why servers might be listed under the 'UNKNOWN' category in the master server. Attempt to show hostnames anyway, to make it a little more obvious who's responsible for those badly configured servers.



git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5656 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2020-03-25 21:29:30 +00:00
parent 9aa87ad28e
commit b63dc8b880
59 changed files with 1970 additions and 421 deletions

View file

@ -469,6 +469,7 @@ SET(FTE_COMMON_FILES
engine/common/q3common.c engine/common/q3common.c
engine/common/qvm.c engine/common/qvm.c
engine/common/sha1.c engine/common/sha1.c
engine/common/sha2.c
engine/common/translate.c engine/common/translate.c
engine/common/zone.c engine/common/zone.c
@ -773,7 +774,7 @@ ELSE()
${FTE_CLIENT_FILES} ${FTE_CLIENT_FILES}
) )
SET_TARGET_PROPERTIES(fteqw PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_DEFINES};${FTE_REVISON}") SET_TARGET_PROPERTIES(fteqw PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_DEFINES};${FTE_REVISON}")
TARGET_LINK_LIBRARIES(fteqw ${FTE_LIBS} ) TARGET_LINK_LIBRARIES(fteqw ${FTE_LIBS})
SET(INSTALLTARGS ${INSTALLTARGS} fteqw) SET(INSTALLTARGS ${INSTALLTARGS} fteqw)
ADD_EXECUTABLE(fteqw-sv ADD_EXECUTABLE(fteqw-sv

View file

@ -859,6 +859,7 @@ COMMON_OBJS = \
huff.o \ huff.o \
md4.o \ md4.o \
sha1.o \ sha1.o \
sha2.o \
log.o \ log.o \
net_chan.o \ net_chan.o \
net_wins.o \ net_wins.o \

View file

@ -1620,12 +1620,13 @@ void CL_UseIndepPhysics(qboolean allow)
} }
else else
{ {
CL_AllowIndependantSendCmd(true);
//shut it down. //shut it down.
runningindepphys = false; //tell thread to exit gracefully runningindepphys = false; //tell thread to exit gracefully
Sys_LockMutex(indeplock);
Sys_WaitOnThread(indepthread); Sys_WaitOnThread(indepthread);
Sys_UnlockMutex(indeplock); indepthread = NULL;
Sys_DestroyMutex(indeplock); Sys_DestroyMutex(indeplock);
indeplock = NULL;
} }
} }
#else #else

View file

@ -1506,6 +1506,7 @@ void CL_Rcon_f (void)
const unsigned char **tokens = alloca(sizeof(*tokens)*(4+Cmd_Argc()*2)); const unsigned char **tokens = alloca(sizeof(*tokens)*(4+Cmd_Argc()*2));
size_t *tokensizes = alloca(sizeof(*tokensizes)*(4+Cmd_Argc()*2)); size_t *tokensizes = alloca(sizeof(*tokensizes)*(4+Cmd_Argc()*2));
int j, k; int j, k;
void *ctx = alloca(hash_sha1.contextsize);
for (j = 0; j < sizeof(time_t); j++) for (j = 0; j < sizeof(time_t); j++)
{ //little-endian byte order, but big-endian nibble order. just screwed. for compat with ezquake. { //little-endian byte order, but big-endian nibble order. just screwed. for compat with ezquake.
@ -1523,9 +1524,11 @@ void CL_Rcon_f (void)
tokens[4+j*2+0] = Cmd_Argv(i+j); tokens[4+j*2+0] = Cmd_Argv(i+j);
tokens[4+j*2+1] = " "; tokens[4+j*2+1] = " ";
} }
hash_sha1.init(ctx);
for (k = 0; k < 4+j*2; k++) for (k = 0; k < 4+j*2; k++)
tokensizes[k] = strlen(tokens[k]); hash_sha1.process(ctx, tokens[k], strlen(tokens[k]));
digestsize = SHA1_m(digest, sizeof(digest), k, tokens, tokensizes); hash_sha1.terminate(digest, ctx);
digestsize = hash_sha1.digestsize;
for (j = 0; j < digestsize; j++) for (j = 0; j < digestsize; j++)
{ {

View file

@ -4517,15 +4517,18 @@ static void CLQ2_ParseConfigString (void)
} }
else if (i == Q2CS_MAPCHECKSUM) else if (i == Q2CS_MAPCHECKSUM)
{ {
extern int map_checksum;
int serverchecksum = atoi(s); int serverchecksum = atoi(s);
int mapchecksum = 0;
if (cl.worldmodel && (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3)) if (cl.worldmodel)
{ {
// the Q2 client normally exits here, however for our purposes we might as well ignore it if (cl.worldmodel->loadstate == MLS_LOADING)
if (map_checksum != serverchecksum) COM_WorkerPartialSync(cl.worldmodel, &cl.worldmodel->loadstate, MLS_LOADING);
Con_Printf(CON_WARNING "WARNING: Client checksum does not match server checksum (%i != %i)", map_checksum, serverchecksum); mapchecksum = cl.worldmodel->checksum;
} }
// the Q2 client normally exits here, however for our purposes we might as well ignore it
if (mapchecksum != serverchecksum)
Con_Printf(CON_WARNING "WARNING: Client checksum does not match server checksum (%i != %i)", mapchecksum, serverchecksum);
} }
} }
#endif #endif

View file

@ -295,8 +295,9 @@ typedef struct
//the light array works thusly: //the light array works thusly:
//dlights are allocated DL_LAST downwards to 0, static wlights are allocated DL_LAST+1 to MAX_RTLIGHTS. //dlights are allocated DL_LAST downwards to 0, static wlights are allocated DL_LAST+1 to MAX_RTLIGHTS.
//thus to clear the dlights but not rtlights, set the first light to RTL_FIRST //thus to clear the dlights but not rtlights, set the first light to RTL_FIRST
#define DL_LAST (sizeof(unsigned int)*8-1) #define dlightbitmask_t size_t
#define RTL_FIRST (sizeof(unsigned int)*8) #define DL_LAST (sizeof(dlightbitmask_t)*8-1)
#define RTL_FIRST (sizeof(dlightbitmask_t)*8)
#define LFLAG_NORMALMODE (1<<0) /*ppl with r_shadow_realtime_dlight*/ #define LFLAG_NORMALMODE (1<<0) /*ppl with r_shadow_realtime_dlight*/
#define LFLAG_REALTIMEMODE (1<<1) /*ppl with r_shadow_realtime_world*/ #define LFLAG_REALTIMEMODE (1<<1) /*ppl with r_shadow_realtime_world*/
@ -1488,6 +1489,7 @@ qboolean CSQC_Accelerometer(float x, float y, float z);
qboolean CSQC_Gyroscope(float x, float y, float z); qboolean CSQC_Gyroscope(float x, float y, float z);
int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation, float pitchmod, float timeofs, unsigned int flags); int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation, float pitchmod, float timeofs, unsigned int flags);
void CSQC_ParseEntities(void); void CSQC_ParseEntities(void);
const char *CSQC_GetExtraFieldInfo(void *went, char *out, size_t outsize);
void CSQC_ResetTrails(void); void CSQC_ResetTrails(void);
qboolean CSQC_DeltaPlayer(int playernum, player_state_t *state); qboolean CSQC_DeltaPlayer(int playernum, player_state_t *state);

View file

@ -1,8 +1,16 @@
//copyright 'Spike', license gplv2+ //copyright 'Spike', license gplv2+
//provides both a package manager and downloads menu. //provides both a package manager and downloads menu.
//FIXME: block downloads of exe/dll/so/etc if not an https url (even if inside zips). also block such files from package lists over http. //FIXME: block downloads of exe/dll/so/etc if not an https url (even if inside zips). also block such files from package lists over http.
//Note: for a while we didn't have strong hashes, nor signing, so we depended upon known-self-signed tls certificates to prove authenticity
//we now have sha256 hashes(and sizes) to ensure that the file we wanted hasn't been changed in transit.
//and we have signature info, to prove that the hash specified was released by a known authority. This means that we should now be able to download such things over http without worries (or at least that we can use an untrustworthy CA that's trusted by insecurity-mafia browsers).
//WARNING: paks/pk3s may still be installed without signatures, without allowing dlls/exes/etc to be installed.
//signaturedata+hashes can be generated with 'fteqw -privkey key.priv -pubkey key.pub -certhost MyAuthority -sign pathtofile', but Auth_GetKnownCertificate will need to be updated for any allowed authorities.
#include "quakedef.h" #include "quakedef.h"
#include "shader.h" #include "shader.h"
#include "netinc.h"
#ifdef PACKAGEMANAGER #ifdef PACKAGEMANAGER
#if !defined(NOBUILTINMENUS) && !defined(SERVERONLY) #if !defined(NOBUILTINMENUS) && !defined(SERVERONLY)
@ -63,6 +71,9 @@ extern cvar_t pm_downloads_url;
#define DPF_PLUGIN (1u<<13) //this is a plugin package, with a dll #define DPF_PLUGIN (1u<<13) //this is a plugin package, with a dll
#define DPF_TRUSTED (1u<<14) //flag used when parsing package lists. if not set then packages will be ignored if they are anything but paks/pk3s #define DPF_TRUSTED (1u<<14) //flag used when parsing package lists. if not set then packages will be ignored if they are anything but paks/pk3s
#define DPF_SIGNATUREREJECTED (1u<<15) //signature is bad
#define DPF_SIGNATUREACCEPTED (1u<<16) //signature is good (required for dll/so/exe files)
#define DPF_SIGNATUREUNKNOWN (1u<<17) //signature is unknown
#define DPF_MARKED (DPF_USERMARKED|DPF_AUTOMARKED) #define DPF_MARKED (DPF_USERMARKED|DPF_AUTOMARKED)
#define DPF_PRESENT (DPF_NATIVE|DPF_CACHED) #define DPF_PRESENT (DPF_NATIVE|DPF_CACHED)
@ -117,6 +128,11 @@ typedef struct package_s {
char *arch; char *arch;
char *qhash; char *qhash;
quint64_t filesize; //in bytes, as part of verifying the hash.
char *filesha1;
char *filesha512;
char *signature;
char *title; char *title;
char *description; char *description;
char *license; char *license;
@ -137,6 +153,7 @@ typedef struct package_s {
enum enum
{ {
DEP_CONFLICT, //don't install if we have the named package installed. DEP_CONFLICT, //don't install if we have the named package installed.
DEP_REPLACE, //obsoletes the specified package (or just acts as a conflict marker for now).
DEP_FILECONFLICT, //don't install if this file already exists. DEP_FILECONFLICT, //don't install if this file already exists.
DEP_REQUIRE, //don't install unless we have the named package installed. DEP_REQUIRE, //don't install unless we have the named package installed.
DEP_RECOMMEND, //like depend, but uninstalling will not bubble. DEP_RECOMMEND, //like depend, but uninstalling will not bubble.
@ -192,6 +209,7 @@ static int downloadablessequence; //bumped any time any package is purged
static void PM_WriteInstalledPackages(void); static void PM_WriteInstalledPackages(void);
static void PM_PreparePackageList(void); static void PM_PreparePackageList(void);
static qboolean PM_SignatureOkay(package_t *p);
static void PM_FreePackage(package_t *p) static void PM_FreePackage(package_t *p)
{ {
@ -252,13 +270,98 @@ static qboolean PM_PurgeOnDisable(package_t *p)
//hashed packages can also be present and not enabled, but only if they're in the cache and not native //hashed packages can also be present and not enabled, but only if they're in the cache and not native
if (*p->gamedir && p->qhash && (p->flags & DPF_PRESENT)) if (*p->gamedir && p->qhash && (p->flags & DPF_PRESENT))
return false; return false;
//FIXME: add basedir-plugins to the package manager so they can be enabled/disabled properly.
//if (p->arch)
// return false;
//all other packages must be deleted to disable them //all other packages must be deleted to disable them
return true; return true;
} }
void PM_ValidateAuthenticity(package_t *p)
{
qbyte hashdata[512];
size_t hashsize = 0;
qbyte signdata[1024];
size_t signsize = 0;
int r;
char authority[MAX_QPATH], *sig;
#if 1
#pragma message("Temporary code.")
//this is temporary code and should be removed once everything else has been fixed.
//ignore the signature (flag as accepted) for any packages with all mirrors on our own update site.
//we can get away with this because we enforce a known certificate for the download.
if (!COM_CheckParm("-notlstrust"))
{
conchar_t musite[256], *e;
char site[256];
char *oldprefix = "http://fte.";
char *newprefix = "https://updates.";
int m;
e = COM_ParseFunString(CON_WHITEMASK, ENGINEWEBSITE, musite, sizeof(musite), false);
COM_DeFunString(musite, e, site, sizeof(site)-1, true, true);
if (!strncmp(site, oldprefix, strlen(oldprefix)))
{
memmove(site+strlen(newprefix), site+strlen(oldprefix), strlen(site)-strlen(oldprefix)+1);
memcpy(site, newprefix, strlen(newprefix));
}
Q_strncatz(site, "/", sizeof(site));
for (m = 0; m < countof(p->mirror); m++)
{
if (p->mirror[m] && strncmp(p->mirror[m], site, strlen(site)))
break; //some other host
}
if (m == countof(p->mirror))
{
p->flags |= DPF_SIGNATUREACCEPTED;
return;
}
}
#endif
*authority = 0;
if (!p->signature)
r = VH_AUTHORITY_UNKNOWN;
else if (!p->filesha512)
r = VH_INCORRECT;
else
{
sig = strchr(p->signature, ':');
if (sig && sig-p->signature<countof(authority)-1)
{
memcpy(authority, p->signature, sig-p->signature);
authority[sig-p->signature] = 0;
sig++;
}
else
sig = p->signature;
hashsize = Base16_DecodeBlock(p->filesha512, hashdata, sizeof(hashdata));
signsize = Base64_DecodeBlock(sig, NULL, signdata, sizeof(signdata));
r = VH_UNSUPPORTED;//preliminary
}
(void)signsize;
(void)hashsize;
//try and get one of our providers to verify it...
#ifdef HAVE_WINSSPI
if (r == VH_UNSUPPORTED)
r = SSPI_VerifyHash(hashdata, hashsize, authority, signdata, signsize);
#endif
#ifdef HAVE_GNUTLS
if (r == VH_UNSUPPORTED)
r = GNUTLS_VerifyHash(hashdata, hashsize, authority, signdata, signsize);
#endif
#ifdef HAVE_OPENSSL
if (r == VH_UNSUPPORTED)
r = OSSL_VerifyHash(hashdata, hashsize, authority, signdata, signsize);
#endif
if (r == VH_CORRECT)
p->flags |= DPF_SIGNATUREACCEPTED;
else if (r == VH_INCORRECT)
p->flags |= DPF_SIGNATUREREJECTED;
else if (p->signature)
p->flags |= DPF_SIGNATUREUNKNOWN;
}
//checks the status of each package //checks the status of each package
static void PM_ValidatePackage(package_t *p) static void PM_ValidatePackage(package_t *p)
{ {
@ -952,6 +1055,8 @@ static qboolean PM_ParsePackageList(const char *f, int parseflags, const char *u
PM_AddDep(p, DEP_REQUIRE, val); PM_AddDep(p, DEP_REQUIRE, val);
else if (!strcmp(key, "conflict")) else if (!strcmp(key, "conflict"))
PM_AddDep(p, DEP_CONFLICT, val); PM_AddDep(p, DEP_CONFLICT, val);
else if (!strcmp(key, "replace"))
PM_AddDep(p, DEP_REPLACE, val);
else if (!strcmp(key, "fileconflict")) else if (!strcmp(key, "fileconflict"))
PM_AddDep(p, DEP_FILECONFLICT, val); PM_AddDep(p, DEP_FILECONFLICT, val);
else if (!strcmp(key, "recommend")) else if (!strcmp(key, "recommend"))
@ -975,6 +1080,14 @@ static qboolean PM_ParsePackageList(const char *f, int parseflags, const char *u
else else
fsroot = FS_ROOT; fsroot = FS_ROOT;
} }
else if (!strcmp(key, "dlsize"))
p->filesize = strtoull(val, NULL, 0);
else if (!strcmp(key, "sha1"))
Z_StrDupPtr(&p->filesha1, val);
else if (!strcmp(key, "sha512"))
Z_StrDupPtr(&p->filesha512, val);
else if (!strcmp(key, "sign"))
Z_StrDupPtr(&p->signature, val);
else else
{ {
Con_DPrintf("Unknown package property\n"); Con_DPrintf("Unknown package property\n");
@ -1051,6 +1164,9 @@ static qboolean PM_ParsePackageList(const char *f, int parseflags, const char *u
p->mirror[m] = Z_StrDup(va("%s%s%s", mirror[m], relurl, ext)); p->mirror[m] = Z_StrDup(va("%s%s%s", mirror[m], relurl, ext));
} }
} }
PM_ValidateAuthenticity(p);
Z_Free(ver); Z_Free(ver);
Z_Free(file); Z_Free(file);
Z_Free(url); Z_Free(url);
@ -1462,19 +1578,20 @@ static void PM_UnmarkPackage(package_t *package, unsigned int markflag)
} }
//just flags, doesn't install //just flags, doesn't install
static void PM_MarkPackage(package_t *package, unsigned int markflag) //returns true if it was marked (or already enabled etc), false if we're not allowed.
static qboolean PM_MarkPackage(package_t *package, unsigned int markflag)
{ {
package_t *o; package_t *o;
struct packagedep_s *dep, *dep2; struct packagedep_s *dep, *dep2;
qboolean replacing = false; qboolean replacing = false;
if (pkg_updating) if (pkg_updating)
return; return false;
if (package->flags & DPF_MARKED) if (package->flags & DPF_MARKED)
{ {
package->flags |= markflag; package->flags |= markflag;
return; //looks like its already picked. marking it again will do no harm. return true; //looks like its already picked. marking it again will do no harm.
} }
#ifndef WEBCLIENT #ifndef WEBCLIENT
@ -1482,10 +1599,13 @@ static void PM_MarkPackage(package_t *package, unsigned int markflag)
if (!(package->flags & DPF_PRESENT)) if (!(package->flags & DPF_PRESENT))
{ //though we can at least unmark it for deletion... { //though we can at least unmark it for deletion...
package->flags &= ~DPF_PURGE; package->flags &= ~DPF_PURGE;
return; return false;
} }
#endif #endif
if (!PM_SignatureOkay(package))
return false;
//any file-conflicts prevent the package from being installable. //any file-conflicts prevent the package from being installable.
//this is mostly for pak1.pak //this is mostly for pak1.pak
for (dep = package->deps; dep; dep = dep->next) for (dep = package->deps; dep; dep = dep->next)
@ -1498,7 +1618,7 @@ static void PM_MarkPackage(package_t *package, unsigned int markflag)
else else
n = dep->name; n = dep->name;
if (PM_CheckFile(n, package->fsroot)) if (PM_CheckFile(n, package->fsroot))
return; return false;
} }
} }
@ -1545,7 +1665,7 @@ static void PM_MarkPackage(package_t *package, unsigned int markflag)
//if we are replacing an existing one, then dependancies are already settled (only because we don't do version deps) //if we are replacing an existing one, then dependancies are already settled (only because we don't do version deps)
if (replacing) if (replacing)
return; return true;
//satisfy our dependancies. //satisfy our dependancies.
for (dep = package->deps; dep; dep = dep->next) for (dep = package->deps; dep; dep = dep->next)
@ -1567,7 +1687,7 @@ static void PM_MarkPackage(package_t *package, unsigned int markflag)
Con_DPrintf("Couldn't find dependancy \"%s\"\n", dep->name); Con_DPrintf("Couldn't find dependancy \"%s\"\n", dep->name);
} }
} }
if (dep->dtype == DEP_CONFLICT) if (dep->dtype == DEP_CONFLICT || dep->dtype == DEP_REPLACE)
{ {
for (;;) for (;;)
{ {
@ -1583,10 +1703,11 @@ static void PM_MarkPackage(package_t *package, unsigned int markflag)
for (o = availablepackages; o; o = o->next) for (o = availablepackages; o; o = o->next)
{ {
for (dep = o->deps; dep; dep = dep->next) for (dep = o->deps; dep; dep = dep->next)
if (dep->dtype == DEP_CONFLICT) if (dep->dtype == DEP_CONFLICT || dep->dtype == DEP_REPLACE)
if (!strcmp(dep->name, package->name)) if (!strcmp(dep->name, package->name))
PM_UnmarkPackage(o, DPF_MARKED); PM_UnmarkPackage(o, DPF_MARKED);
} }
return true;
} }
static qboolean PM_NameIsInStrings(const char *strings, const char *match) static qboolean PM_NameIsInStrings(const char *strings, const char *match)
@ -2086,6 +2207,11 @@ static void PM_WriteInstalledPackages(void)
Q_strncatz(buf, " ", sizeof(buf)); Q_strncatz(buf, " ", sizeof(buf));
COM_QuotedConcat(va("preview=%s", p->previewimage), buf, sizeof(buf)); COM_QuotedConcat(va("preview=%s", p->previewimage), buf, sizeof(buf));
} }
if (p->filesize)
{
Q_strncatz(buf, " ", sizeof(buf));
COM_QuotedConcat(va("filesize=%s", p->previewimage), buf, sizeof(buf));
}
if (p->fsroot == FS_BINARYPATH) if (p->fsroot == FS_BINARYPATH)
{ {
@ -2110,6 +2236,11 @@ static void PM_WriteInstalledPackages(void)
Q_strncatz(buf, " ", sizeof(buf)); Q_strncatz(buf, " ", sizeof(buf));
COM_QuotedConcat(va("conflict=%s", dep->name), buf, sizeof(buf)); COM_QuotedConcat(va("conflict=%s", dep->name), buf, sizeof(buf));
} }
else if (dep->dtype == DEP_REPLACE)
{
Q_strncatz(buf, " ", sizeof(buf));
COM_QuotedConcat(va("replace=%s", dep->name), buf, sizeof(buf));
}
else if (dep->dtype == DEP_FILECONFLICT) else if (dep->dtype == DEP_FILECONFLICT)
{ {
Q_strncatz(buf, " ", sizeof(buf)); Q_strncatz(buf, " ", sizeof(buf));
@ -2224,11 +2355,11 @@ static int QDECL PM_ExtractFiles(const char *fname, qofs_t fsize, time_t mtime,
n = fname; n = fname;
if (FS_WriteFile(n, f, loc.len, p->fsroot)) if (FS_WriteFile(n, f, loc.len, p->fsroot))
p->flags |= DPF_NATIVE|DPF_ENABLED; p->flags |= DPF_NATIVE|DPF_ENABLED;
free(f);
//keep track of the installed files, so we can delete them properly after. //keep track of the installed files, so we can delete them properly after.
PM_AddDep(p, DEP_FILE, fname); PM_AddDep(p, DEP_FILE, fname);
} }
free(f);
} }
return 1; return 1;
} }
@ -2250,9 +2381,12 @@ static void PM_Download_Got(struct dl_download *dl)
if (dl->file) if (dl->file)
{ {
VFS_CLOSE(dl->file); if (!VFS_CLOSE(dl->file))
successful = false;
dl->file = NULL; dl->file = NULL;
} }
else
successful = false;
if (p) if (p)
{ {
@ -2434,6 +2568,111 @@ static char *PM_GetTempName(package_t *p)
Z_Free(ts); Z_Free(ts);
return Z_StrDup(destname); return Z_StrDup(destname);
} }
typedef struct {
vfsfile_t pub;
vfsfile_t *f;
hashfunc_t *hashfunc;
qofs_t sz;
qofs_t needsize;
qboolean fail;
qbyte need[256];
qbyte ctx[1];
char *fname;
} hashfile_t;
static int QDECL SHA1File_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestowrite)
{
hashfile_t *f = (hashfile_t*)file;
f->hashfunc->process(&f->ctx, buffer, bytestowrite);
if (bytestowrite != VFS_WRITE(f->f, buffer, bytestowrite))
f->fail = true; //something went wrong.
if (f->fail)
return -1; //error! abort! fail! give up!
f->sz += bytestowrite;
return bytestowrite;
}
static void QDECL SHA1File_Flush (struct vfsfile_s *file)
{
hashfile_t *f = (hashfile_t*)file;
VFS_FLUSH(f->f);
}
static qboolean QDECL SHA1File_Close (struct vfsfile_s *file)
{
qbyte digest[256];
hashfile_t *f = (hashfile_t*)file;
if (!VFS_CLOSE(f->f))
f->fail = true; //something went wrong.
f->hashfunc->terminate(digest, &f->ctx);
if (f->fail)
Con_Printf("Filesystem problems downloading %s\n", f->fname); //don't error if we failed on actual disk problems
else if (f->sz != f->needsize)
{
Con_Printf("Download truncated: %s\n", f->fname); //don't error if we failed on actual disk problems
f->fail = true;
}
else if (memcmp(digest, f->need, f->hashfunc->digestsize))
{
Con_Printf("Invalid hash for downloaded file %s, try again later?\n", f->fname);
f->fail = true;
}
return !f->fail; //true if all okay!
}
static vfsfile_t *FS_Sha1_ValidateWrites(vfsfile_t *f, const char *fname, qofs_t needsize, hashfunc_t *hashfunc, const char *hash)
{ //wraps a writable file with a layer that'll cause failures when the hash differs from what we expect.
if (f)
{
hashfile_t *n = Z_Malloc(sizeof(*n) + hashfunc->contextsize + strlen(fname));
n->pub.WriteBytes = SHA1File_WriteBytes;
n->pub.Flush = SHA1File_Flush;
n->pub.Close = SHA1File_Close;
n->pub.seekstyle = SS_UNSEEKABLE;
n->f = f;
n->hashfunc = hashfunc;
n->fname = n->ctx+hashfunc->contextsize;
strcpy(n->fname, fname);
n->needsize = needsize;
Base16_DecodeBlock(hash, n->need, sizeof(n->need));
n->fail = false;
f = &n->pub;
n->hashfunc->init(&n->ctx);
}
return f;
}
static qboolean PM_SignatureOkay(package_t *p)
{
struct packagedep_s *dep;
char ext[MAX_QPATH];
// if (p->flags & (DPF_SIGNATUREREJECTED|DPF_SIGNATUREUNKNOWN)) //the sign key didn't match its sha512 hash
// return false; //just block it entirely.
if (p->flags & DPF_SIGNATUREACCEPTED) //sign value is present and correct
return true; //go for it.
if (p->flags & DPF_PRESENT)
return true; //we don't know where it came from, but someone manually installed it...
//packages without a signature are only allowed under some limited conditions.
//basically we only allow meta packages, pk3s, and paks.
if (p->extract == EXTRACT_ZIP)
return false; //extracting files is bad (there might be some weird .pif or whatever file in there, don't risk it)
for (dep = p->deps; dep; dep = dep->next)
{
if (dep->dtype != DEP_FILE)
continue;
COM_FileExtension(dep->name, ext, sizeof(ext));
if ((!stricmp(ext, "pak") || !stricmp(ext, "pk3")) && p->qhash)
;
else
return false;
}
return true;
}
#endif #endif
/*static void PM_AddDownloadedPackage(const char *filename) /*static void PM_AddDownloadedPackage(const char *filename)
@ -2545,6 +2784,11 @@ static void PM_StartADownload(void)
continue; continue;
} }
if (!PM_SignatureOkay(p) || (qofs_t)p->filesize != p->filesize)
{
p->flags &= ~DPF_MARKED; //refusing to do it.
continue;
}
temp = PM_GetTempName(p); temp = PM_GetTempName(p);
@ -2584,6 +2828,11 @@ static void PM_StartADownload(void)
continue; continue;
} }
if (p->filesha512 && tmpfile)
tmpfile = FS_Sha1_ValidateWrites(tmpfile, p->name, p->filesize, &hash_sha512, p->filesha512);
else if (p->filesha1 && tmpfile)
tmpfile = FS_Sha1_ValidateWrites(tmpfile, p->name, p->filesize, &hash_sha1, p->filesha1);
if (tmpfile) if (tmpfile)
{ {
p->download = HTTP_CL_Get(mirror, NULL, PM_Download_Got); p->download = HTTP_CL_Get(mirror, NULL, PM_Download_Got);
@ -2999,6 +3248,7 @@ void PM_Command_f(void)
{ {
for (p = availablepackages; p; p=p->next) for (p = availablepackages; p; p=p->next)
{ {
char quoted[8192];
const char *status; const char *status;
char *markup; char *markup;
if ((p->flags & DPF_HIDDEN) && !(p->flags & (DPF_MARKED|DPF_ENABLED|DPF_PURGE|DPF_CACHED))) if ((p->flags & DPF_HIDDEN) && !(p->flags & (DPF_MARKED|DPF_ENABLED|DPF_PURGE|DPF_CACHED)))
@ -3035,7 +3285,13 @@ void PM_Command_f(void)
else else
status = ""; status = "";
Con_Printf(" ^["S_COLOR_GRAY"%s%s%s%s%s^] %s"S_COLOR_GRAY" %s (%s%s)\n", p->category?p->category:"", markup, p->name, p->arch?":":"", p->arch?p->arch:"", status, strcmp(p->name, p->title)?p->title:"", p->version, (p->flags&DPF_TESTING)?"-testing":""); Con_Printf(" ^["S_COLOR_GRAY"%s%s%s%s%s^] %s"S_COLOR_GRAY" %s (%s%s)", p->category?p->category:"", markup, p->name, p->arch?":":"", p->arch?p->arch:"", status, strcmp(p->name, p->title)?p->title:"", p->version, (p->flags&DPF_TESTING)?"-testing":"");
if (!(p->flags&DPF_MARKED) && p == PM_FindPackage(p->name))
Con_Printf(" ^[[Add]\\type\\pkg add %s;pkg apply^]", COM_QuotedString(p->name, quoted, sizeof(quoted), false));
if ((p->flags&DPF_MARKED) && p == PM_MarkedPackage(p->name, DPF_MARKED))
Con_Printf(" ^[[Remove]\\type\\pkg rem %s;pkg apply^]", COM_QuotedString(p->name, quoted, sizeof(quoted), false));
Con_Printf("\n");
} }
Con_Printf("<end of list>\n"); Con_Printf("<end of list>\n");
} }
@ -3401,6 +3657,8 @@ static void MD_Draw (int x, int y, struct menucustom_s *c, struct emenu_s *m)
if (!PM_CheckPackageFeatures(p)) if (!PM_CheckPackageFeatures(p))
Draw_FunStringWidth(0, y, "!", x+8, true, true); Draw_FunStringWidth(0, y, "!", x+8, true, true);
if (!PM_SignatureOkay(p))
Draw_FunStringWidth(0, y, "^b!", x+8, true, true);
// if (!(p->flags & (DPF_ENABLED|DPF_MARKED|DPF_PRESENT)) // if (!(p->flags & (DPF_ENABLED|DPF_MARKED|DPF_PRESENT))
// continue; // continue;
@ -3616,11 +3874,25 @@ static int MD_AddItemsToDownloadMenu(emenu_t *m, int y, const char *pathprefix)
slash = strchr(p->category+prefixlen, '/'); slash = strchr(p->category+prefixlen, '/');
if (!slash) if (!slash)
{ {
char *desc; char *head;
char *desc = p->description;
if (p->author || p->license || p->website) if (p->author || p->license || p->website)
desc = va("^aauthor: ^a%s\n^alicense: ^a%s\n^awebsite: ^a%s\n%s", p->author?p->author:"^hUnknown^h", p->license?p->license:"^hUnknown^h", p->website?p->website:"^hUnknown^h", p->description); head = va("^aauthor:^U00A0^a%s\n^alicense:^U00A0^a%s\n^awebsite:^U00A0^a%s\n", p->author?p->author:"^hUnknown^h", p->license?p->license:"^hUnknown^h", p->website?p->website:"^hUnknown^h");
else else
desc = p->description; head = NULL;
if (p->filesize)
{
if (!head)
head = "";
if (p->filesize < 1024)
head = va("%s^asize:^U00A0^a%.4f bytes\n", head, (double)p->filesize);
else if (p->filesize < 1024*1024)
head = va("%s^asize:^U00A0^a%.4f KB\n", head, (p->filesize/(1024.0)));
else if (p->filesize < 1024*1024*1024)
head = va("%s^asize:^U00A0^a%.4f MB\n", head, (p->filesize/(1024.0*1024)));
else
head = va("%s^asize:^U00A0^a%.4f GB\n", head, (p->filesize/(1024.0*1024*1024)));
}
for (dep = p->deps; dep; dep = dep->next) for (dep = p->deps; dep; dep = dep->next)
{ {
@ -3630,12 +3902,28 @@ static int MD_AddItemsToDownloadMenu(emenu_t *m, int y, const char *pathprefix)
if (!PM_CheckFeature(dep->name, &featname, &enablecmd)) if (!PM_CheckFeature(dep->name, &featname, &enablecmd))
{ {
if (enablecmd) if (enablecmd)
desc = va("^aDisabled: ^a%s\n%s", featname, desc); head = va("^aDisabled: ^a%s\n%s", featname, head?head:"");
else else
desc = va("^aUnavailable: ^a%s\n%s", featname, desc); head = va("^aUnavailable: ^a%s\n%s", featname, head?head:"");
} }
} }
} }
if (!PM_SignatureOkay(p))
{
if (!p->signature)
head = va(CON_ERROR"Signature missing"CON_DEFAULT"\n%s", head?head:""); //some idiot forgot to include a signature
else if (p->flags & DPF_SIGNATUREREJECTED)
head = va(CON_ERROR"Signature invalid"CON_DEFAULT"\n%s", head?head:""); //some idiot got the wrong auth/sig/hash
else if (p->flags & DPF_SIGNATUREUNKNOWN)
head = va(CON_ERROR"Signature is not trusted"CON_DEFAULT"\n%s", head?head:""); //clientside permission.
else
head = va(CON_ERROR"Unable to verify signature"CON_DEFAULT"\n%s", head?head:""); //clientside problem.
}
if (head && desc)
desc = va("%s\n%s", head, desc);
else if (head)
desc = head;
c = MC_AddCustom(m, 0, y, p, downloadablessequence, desc); c = MC_AddCustom(m, 0, y, p, downloadablessequence, desc);
c->draw = MD_Draw; c->draw = MD_Draw;

View file

@ -2830,10 +2830,10 @@ void M_Menu_Video_f (void)
}; };
static const char *srgbopts[] = { static const char *srgbopts[] = {
"Non-Linear", "Non-Linear", //0 (legacy buggy linear->srgb non-transforms)
"sRGB-Aware (PBR)", "sRGB-Aware", //1 (linear->srgb transforms)
"Linear (HDR)", "Linear (HDR)", //2 (try to use a float framebuffer, otherwise fall back on srgb framebuffer)
"Linearised", //-1 "Linearised", //-1
NULL NULL
}; };
static const char *srgbvalues[] = { "0", "1", "2", "-1", NULL}; static const char *srgbvalues[] = { "0", "1", "2", "-1", NULL};

View file

@ -608,9 +608,6 @@ static void CS_CheckVelocity(csqcedict_t *ent)
static void cs_getframestate(csqcedict_t *in, unsigned int rflags, framestate_t *fte_restrict out) static void cs_getframestate(csqcedict_t *in, unsigned int rflags, framestate_t *fte_restrict out)
{ {
//FTE_CSQC_HALFLIFE_MODELS //FTE_CSQC_HALFLIFE_MODELS
@ -1052,6 +1049,53 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *fte_restrict in, entity_t *ft
return true; return true;
} }
const char *CSQC_GetExtraFieldInfo(void *went, char *out, size_t outsize)
{
csqcedict_t *ent = went;
char *r = out;
char *e = out+outsize;
int i;
skinfile_t *sk = Mod_LookupSkin((ent->skinobject<0)?-ent->skinobject:ent->skinobject);
if (sk)
{
Q_snprintfz(out, e-out, "skin %s\nrefs %i\n", sk->skinname, sk->refcount);
out+=strlen(out);
for (i = 0; i < sk->nummappings; i++)
{
Q_snprintfz(out, e-out, "replace \"%s\" \"%s\"\n", sk->mappings[i].surface, sk->mappings[i].shader?sk->mappings[i].shader->name:"NULL SHADER");
out+=strlen(out);
}
for (i = 0; i < MAX_GEOMSETS; i++)
{
if (sk->geomset[i])
{
Q_snprintfz(out, e-out, "geomset %i %i\n", i, sk->geomset[i]);
out+=strlen(out);
}
}
#ifdef QWSKINS
if (*sk->qwskinname)
{
Q_snprintfz(out, e-out, "qwskin %s\n", sk->qwskinname);
out+=strlen(out);
}
if (sk->q1upper != Q1UNSPECIFIED)
{
Q_snprintfz(out, e-out, "q1upper %#x\n", sk->q1upper);
out+=strlen(out);
}
if (sk->q1lower != Q1UNSPECIFIED)
{
Q_snprintfz(out, e-out, "q1lower %#x\n", sk->q1lower);
out+=strlen(out);
}
#endif
return r;
}
return r==out?NULL:r;
}
static void QCBUILTIN PF_cs_makestatic (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_cs_makestatic (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ //still does a remove. { //still does a remove.
csqcedict_t *in = (void*)G_EDICT(prinst, OFS_PARM0); csqcedict_t *in = (void*)G_EDICT(prinst, OFS_PARM0);

View file

@ -325,9 +325,9 @@ void Surf_LessenStains(void)
R_AddDynamicLights R_AddDynamicLights
=============== ===============
*/ */
static void Surf_AddDynamicLights (msurface_t *surf) static void Surf_AddDynamicLights_Lum (msurface_t *surf)
{ {
int lnum; size_t lnum;
int sd, td; int sd, td;
float dist, rad, minlight; float dist, rad, minlight;
vec3_t impact, local; vec3_t impact, local;
@ -344,7 +344,7 @@ static void Surf_AddDynamicLights (msurface_t *surf)
for (lnum=rtlights_first; lnum<RTL_FIRST; lnum++) for (lnum=rtlights_first; lnum<RTL_FIRST; lnum++)
{ {
if ( !(surf->dlightbits & (1<<lnum) ) ) if ( !(surf->dlightbits & ((dlightbitmask_t)1u<<lnum) ) )
continue; // not lit by this light continue; // not lit by this light
if (!(cl_dlights[lnum].flags & LFLAG_LIGHTMAP)) if (!(cl_dlights[lnum].flags & LFLAG_LIGHTMAP))
@ -415,7 +415,7 @@ static void Surf_AddDynamicLightNorms (msurface_t *surf)
for (lnum=rtlights_first; lnum<RTL_FIRST; lnum++) for (lnum=rtlights_first; lnum<RTL_FIRST; lnum++)
{ {
if ( !(surf->dlightbits & (1<<lnum) ) ) if ( !(surf->dlightbits & ((dlightbitmask_t)1u<<lnum) ) )
continue; // not lit by this light continue; // not lit by this light
if (!(cl_dlights[lnum].flags & LFLAG_ALLOW_LMHACK)) if (!(cl_dlights[lnum].flags & LFLAG_ALLOW_LMHACK))
@ -471,7 +471,7 @@ static void Surf_AddDynamicLightNorms (msurface_t *surf)
*/ */
#ifdef PEXT_LIGHTSTYLECOL #ifdef PEXT_LIGHTSTYLECOL
static void Surf_AddDynamicLightsColours (msurface_t *surf) static void Surf_AddDynamicLights_RGB (msurface_t *surf)
{ {
int lnum; int lnum;
int sd, td; int sd, td;
@ -492,7 +492,7 @@ static void Surf_AddDynamicLightsColours (msurface_t *surf)
for (lnum=rtlights_first; lnum<RTL_FIRST; lnum++) for (lnum=rtlights_first; lnum<RTL_FIRST; lnum++)
{ {
if ( !(surf->dlightbits & (1<<lnum) ) ) if ( !(surf->dlightbits & ((dlightbitmask_t)1u<<lnum) ) )
continue; // not lit by this light continue; // not lit by this light
rad = cl_dlights[lnum].radius; rad = cl_dlights[lnum].radius;
@ -637,7 +637,7 @@ static void Surf_BuildDeluxMap (model_t *wmodel, msurface_t *surf, qbyte *dest,
{ {
case LM_E5BGR9: case LM_E5BGR9:
deluxmap = ((surf->samples - wmodel->lightdata)/4)*3 + wmodel->deluxdata; deluxmap = ((surf->samples - wmodel->lightdata)/4)*3 + wmodel->deluxdata;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]; scale = d_lightstylevalue[surf->styles[maps]];
for (i=0 ; i<size ; i++) for (i=0 ; i<size ; i++)
@ -654,7 +654,7 @@ static void Surf_BuildDeluxMap (model_t *wmodel, msurface_t *surf, qbyte *dest,
break; break;
case LM_RGB8: case LM_RGB8:
deluxmap = surf->samples - wmodel->lightdata + wmodel->deluxdata; deluxmap = surf->samples - wmodel->lightdata + wmodel->deluxdata;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]; scale = d_lightstylevalue[surf->styles[maps]];
for (i=0 ; i<size ; i++) for (i=0 ; i<size ; i++)
@ -670,7 +670,7 @@ static void Surf_BuildDeluxMap (model_t *wmodel, msurface_t *surf, qbyte *dest,
break; break;
case LM_L8: case LM_L8:
deluxmap = (surf->samples - wmodel->lightdata)*3 + wmodel->deluxdata; deluxmap = (surf->samples - wmodel->lightdata)*3 + wmodel->deluxdata;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]; scale = d_lightstylevalue[surf->styles[maps]];
for (i=0 ; i<size ; i++) for (i=0 ; i<size ; i++)
@ -769,22 +769,22 @@ store:
static unsigned int Surf_PackE5BRG9(int r, int g, int b, int shift) static unsigned int Surf_PackE5BRG9(int r, int g, int b, int shift)
{ //5 bits exponent, 3*9 bits of mantissa. no sign bit. { //5 bits exponent, 3*9 bits of mantissa. no sign bit.
int e = 0; int e = 0;
float m = max(max(r, g), b) / (float)(1<<shift); float m = max(max(r, g), b) / (float)(1u<<shift);
float scale; float scale;
if (m >= 0.5) if (m >= 0.5)
{ //positive exponent { //positive exponent
while (m >= (1<<(e)) && e < 30-15) //don't do nans. while (m >= (1u<<(e)) && e < 30-15) //don't do nans.
e++; e++;
} }
else else
{ //negative exponent... { //negative exponent...
while (m < 1/(1<<-e) && e > -15) //don't do denormals. while (m < 1/(1u<<-e) && e > -15) //don't do denormals.
e--; e--;
} }
scale = pow(2, e-9); scale = pow(2, e-9);
scale *= (1<<shift); scale *= (1u<<shift);
r = bound(0, r/scale + 0.5, 0x1ff); r = bound(0, r/scale + 0.5, 0x1ff);
g = bound(0, g/scale + 0.5, 0x1ff); g = bound(0, g/scale + 0.5, 0x1ff);
@ -794,7 +794,9 @@ static unsigned int Surf_PackE5BRG9(int r, int g, int b, int shift)
} }
static unsigned short Surf_GenHalf(float val) static unsigned short Surf_GenHalf(float val)
{ { //1-bit sign (ignored here)
//5-bit exponent (biased by 15)
//10-bit mantissa (normalised, so effectively 11 bits when exponent!=0)
union union
{ {
float f; float f;
@ -809,7 +811,7 @@ static unsigned short Surf_GenHalf(float val)
if (e > 15) if (e > 15)
m = 0; //infinity instead of a nan m = 0; //infinity instead of a nan
else else
m = (u.u&((1<<23)-1))>>13; m = (u.u&((1u<<23)-1))>>13;
return ((e+15)<<10) | m; return ((e+15)<<10) | m;
} }
static void Surf_PackRGB16F(void *result, int r, int g, int b, int one) static void Surf_PackRGB16F(void *result, int r, int g, int b, int one)
@ -830,10 +832,10 @@ static void Surf_PackRGB16F(void *result, int r, int g, int b, int one)
((unsigned short*)result)[0] = Surf_GenHalf(r / (float)one); ((unsigned short*)result)[0] = Surf_GenHalf(r / (float)one);
((unsigned short*)result)[1] = Surf_GenHalf(g / (float)one); ((unsigned short*)result)[1] = Surf_GenHalf(g / (float)one);
((unsigned short*)result)[2] = Surf_GenHalf(b / (float)one); ((unsigned short*)result)[2] = Surf_GenHalf(b / (float)one);
((unsigned short*)result)[3] = /*Surf_GenHalf(1.0);*/0x0f<<10; //a standard ieee float should have all but the lead bit set of its exponent, and its mantissa 0. ((unsigned short*)result)[3] = /*Surf_GenHalf(1.0);*/0x0fu<<10; //a standard ieee float should have all but the lead bit set of its exponent, and its mantissa 0.
#endif #endif
} }
static void Surf_PackRGB32F(void *result, int r, int g, int b, int one) static void Surf_PackRGBX32F(void *result, int r, int g, int b, int one)
{ {
((float*)result)[0] = r/(float)one; ((float*)result)[0] = r/(float)one;
((float*)result)[1] = g/(float)one; ((float*)result)[1] = g/(float)one;
@ -886,7 +888,7 @@ static void Surf_StoreLightmap_RGB(qbyte *dest, unsigned int *bl, int smax, int
b *= 1023.0/m; b *= 1023.0/m;
} }
*(unsigned int*)dest = (3<<30) | ((b&0x3ff)<<20) | ((g&0x3ff)<<10) | (r&0x3ff); *(unsigned int*)dest = (3u<<30) | ((b&0x3ff)<<20) | ((g&0x3ff)<<10) | (r&0x3ff);
dest += 4; dest += 4;
} }
if (stainsrc) if (stainsrc)
@ -944,6 +946,7 @@ static void Surf_StoreLightmap_RGB(qbyte *dest, unsigned int *bl, int smax, int
} }
break; break;
case PTI_RGBA32F: case PTI_RGBA32F:
shift = 1u<<(shift+8);
stride = (lm->width-smax)<<4; stride = (lm->width-smax)<<4;
for (i=0 ; i<tmax ; i++, dest += stride) for (i=0 ; i<tmax ; i++, dest += stride)
{ {
@ -960,7 +963,7 @@ static void Surf_StoreLightmap_RGB(qbyte *dest, unsigned int *bl, int smax, int
b = (127+b*(*stainsrc++)) >> 8; b = (127+b*(*stainsrc++)) >> 8;
} }
Surf_PackRGB32F(dest, r,g,b,1<<(shift+8)); Surf_PackRGBX32F(dest, r,g,b,shift);
dest += sizeof(float)*4; dest += sizeof(float)*4;
} }
if (stainsrc) if (stainsrc)
@ -1312,7 +1315,7 @@ static void Surf_StoreLightmap_RGB(qbyte *dest, unsigned int *bl, int smax, int
break; break;
} }
} }
static void Surf_StoreLightmap_Grey(qbyte *dest, unsigned int *bl, int smax, int tmax, unsigned int shift, stmap *stainsrc, unsigned int lmwidth) static void Surf_StoreLightmap_Lum(qbyte *dest, unsigned int *bl, int smax, int tmax, unsigned int shift, stmap *stainsrc, unsigned int lmwidth)
{ {
int t; int t;
unsigned int i, j; unsigned int i, j;
@ -1414,7 +1417,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
t = (-1-ambient)*255; t = (-1-ambient)*255;
for (i=0 ; i<size*3 ; i++) for (i=0 ; i<size*3 ; i++)
blocklights[i] = t; blocklights[i] = t;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS ; maps++)
{ {
surf->cached_light[maps] = -1-ambient; surf->cached_light[maps] = -1-ambient;
surf->cached_colour[maps] = 0xff; surf->cached_colour[maps] = 0xff;
@ -1461,7 +1464,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
switch(currentmodel->lightmaps.fmt) switch(currentmodel->lightmaps.fmt)
{ {
case LM_E5BGR9: case LM_E5BGR9:
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction
surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey;
@ -1481,7 +1484,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
} }
break; break;
case LM_RGB8: case LM_RGB8:
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]];
surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey;
@ -1502,7 +1505,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
break; break;
case LM_L8: case LM_L8:
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ;
maps++) maps++)
{ {
surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction
@ -1529,7 +1532,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
// add all the dynamic lights // add all the dynamic lights
if (surf->dlightframe == r_framecount) if (surf->dlightframe == r_framecount)
Surf_AddDynamicLightsColours (surf); Surf_AddDynamicLights_RGB (surf);
Surf_StoreLightmap_RGB(dest, blocklights, smax, tmax, shift, stainsrc, lm); Surf_StoreLightmap_RGB(dest, blocklights, smax, tmax, shift, stainsrc, lm);
} }
@ -1541,7 +1544,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
t = (-1-ambient)*255; t = (-1-ambient)*255;
for (i=0 ; i<size ; i++) for (i=0 ; i<size ; i++)
blocklights[i] = t; blocklights[i] = t;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS ; maps++)
{ {
surf->cached_light[maps] = -1-ambient; surf->cached_light[maps] = -1-ambient;
surf->cached_colour[maps] = 0xff; surf->cached_colour[maps] = 0xff;
@ -1581,7 +1584,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
switch(currentmodel->lightmaps.fmt) switch(currentmodel->lightmaps.fmt)
{ {
case LM_E5BGR9: case LM_E5BGR9:
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]; scale = d_lightstylevalue[surf->styles[maps]];
surf->cached_light[maps] = scale; // 8.8 fraction surf->cached_light[maps] = scale; // 8.8 fraction
@ -1595,7 +1598,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
} }
break; break;
case LM_RGB8: case LM_RGB8:
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]; scale = d_lightstylevalue[surf->styles[maps]];
surf->cached_light[maps] = scale; // 8.8 fraction surf->cached_light[maps] = scale; // 8.8 fraction
@ -1606,7 +1609,7 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
} }
break; break;
case LM_L8: case LM_L8:
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]; scale = d_lightstylevalue[surf->styles[maps]];
surf->cached_light[maps] = scale; // 8.8 fraction surf->cached_light[maps] = scale; // 8.8 fraction
@ -1620,10 +1623,10 @@ static void Surf_BuildLightMap (model_t *currentmodel, msurface_t *surf, int map
} }
// add all the dynamic lights // add all the dynamic lights
if (surf->dlightframe == r_framecount) if (surf->dlightframe == r_framecount)
Surf_AddDynamicLights (surf); Surf_AddDynamicLights_Lum (surf);
} }
Surf_StoreLightmap_Grey(dest, blocklights, smax, tmax, shift, stainsrc, lm->width); Surf_StoreLightmap_Lum(dest, blocklights, smax, tmax, shift, stainsrc, lm->width);
} }
} }
@ -1682,44 +1685,33 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
{ {
// set to full bright if no light data // set to full bright if no light data
if (ambient < 0) if (ambient < 0)
{ { //abslight for hexen2
t = (-1-ambient)*255; t = (-1-ambient)*255;
for (i=0 ; i<size*3 ; i++) for (i=0 ; i<size*3 ; i++)
{ {
blocklights[i] = t; blocklights[i] = t;
} }
for (maps = 0 ; maps < MAXQ1LIGHTMAPS ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS ; maps++)
{ {
surf->cached_light[maps] = -1-ambient; surf->cached_light[maps] = -1-ambient;
surf->cached_colour[maps] = 0xff; surf->cached_colour[maps] = 0xff;
} }
} }
else if (r_fullbright.value>0) //not qw else if (r_fullbright.value>0)
{ { //fullbright cheat
for (i=0 ; i<size*3 ; i++) for (i=0 ; i<size*3 ; i++)
{ {
blocklights[i] = r_fullbright.value*255*256; blocklights[i] = r_fullbright.value*255*256;
} }
} }
else if (!wmodel->lightdata) else if (!wmodel->lightdata)
{ { /*fullbright if map is not lit. but not overbright*/
/*fullbright if map is not lit. but not overbright*/
for (i=0 ; i<size*3 ; i++) for (i=0 ; i<size*3 ; i++)
{ {
blocklights[i] = 128*256; blocklights[i] = 128*256;
} }
} }
else if (!surf->samples)
{
/*no samples, but map is otherwise lit = pure black*/
for (i=0 ; i<size*3 ; i++)
{
blocklights[i] = 0;
}
surf->cached_light[0] = 0;
surf->cached_colour[0] = 0;
}
else else
{ {
// clear to no light // clear to no light
@ -1758,7 +1750,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
else switch(cl.worldmodel->lightmaps.fmt) else switch(cl.worldmodel->lightmaps.fmt)
{ {
case LM_E5BGR9: case LM_E5BGR9:
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction
surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey;
@ -1768,7 +1760,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
for (i=0 ; i<size ; i++) for (i=0 ; i<size ; i++)
{ {
unsigned int l = ((unsigned int*)src)[i]; unsigned int l = ((unsigned int*)src)[i];
float e = rgb9e5tab[l>>27]*(1<<7); float e = rgb9e5tab[l>>27]*(1u<<7);
blocklights[i*3+0] += scalergb[0] * e * ((l>> 0)&0x1ff); blocklights[i*3+0] += scalergb[0] * e * ((l>> 0)&0x1ff);
blocklights[i*3+1] += scalergb[1] * e * ((l>> 9)&0x1ff); blocklights[i*3+1] += scalergb[1] * e * ((l>> 9)&0x1ff);
blocklights[i*3+2] += scalergb[2] * e * ((l>>18)&0x1ff); blocklights[i*3+2] += scalergb[2] * e * ((l>>18)&0x1ff);
@ -1778,7 +1770,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
} }
break; break;
case LM_RGB8: case LM_RGB8:
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]];
surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey;
@ -1799,7 +1791,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
break; break;
case LM_L8: case LM_L8:
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ;
maps++) maps++)
{ {
surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction surf->cached_light[maps] = scale = d_lightstylevalue[surf->styles[maps]]; // 8.8 fraction
@ -1846,16 +1838,11 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
surf->cached_light[0] = d_lightstylevalue[0]; surf->cached_light[0] = d_lightstylevalue[0];
surf->cached_colour[0] = cl_lightstyle[0].colourkey; surf->cached_colour[0] = cl_lightstyle[0].colourkey;
} }
else if (!surf->samples)
{
for (i=0 ; i<size ; i++)
blocklights[i] = 0;
}
else else
{ {
// clear to no light // clear to no light
for (i=0 ; i<size ; i++) for (i=0 ; i<size ; i++)
blocklights[i] = 0; blocklights[i] = ambient;
// add all the lightmaps // add all the lightmaps
if (src) if (src)
@ -1863,38 +1850,41 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
switch(cl.worldmodel->lightmaps.fmt) switch(cl.worldmodel->lightmaps.fmt)
{ {
case LM_E5BGR9: case LM_E5BGR9:
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]; scale = d_lightstylevalue[surf->styles[maps]];
surf->cached_light[maps] = scale; // 8.8 fraction surf->cached_light[maps] = scale; // 8.8 fraction
surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey;
for (i=0 ; i<size ; i++) if (scale)
{ for (i=0 ; i<size ; i++)
unsigned int lm = ((unsigned int *)lightmap)[i]; {
blocklights[i] += max3(((lm>>0)&0x1ff),((lm>>9)&0x1ff),((lm>>18)&0x1ff)) * scale * (rgb9e5tab[lm>>27]*(1<<7)); unsigned int lm = ((unsigned int *)lightmap)[i];
} blocklights[i] += max3(((lm>>0)&0x1ff),((lm>>9)&0x1ff),((lm>>18)&0x1ff)) * scale * (rgb9e5tab[lm>>27]*(1<<7));
}
lightmap += size*4; // skip to next lightmap lightmap += size*4; // skip to next lightmap
} }
break; break;
case LM_RGB8: case LM_RGB8:
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]; scale = d_lightstylevalue[surf->styles[maps]];
surf->cached_light[maps] = scale; // 8.8 fraction surf->cached_light[maps] = scale; // 8.8 fraction
surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey;
for (i=0 ; i<size ; i++) if (scale)
blocklights[i] += max3(src[i*3],src[i*3+1],src[i*3+2]) * scale; for (i=0 ; i<size ; i++)
blocklights[i] += max3(src[i*3],src[i*3+1],src[i*3+2]) * scale;
src += size*3; // skip to next lightmap src += size*3; // skip to next lightmap
} }
break; break;
case LM_L8: case LM_L8:
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]; scale = d_lightstylevalue[surf->styles[maps]];
surf->cached_light[maps] = scale; // 8.8 fraction surf->cached_light[maps] = scale; // 8.8 fraction
surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey; surf->cached_colour[maps] = cl_lightstyle[surf->styles[maps]].colourkey;
for (i=0 ; i<size ; i++) if (scale)
blocklights[i] += src[i] * scale; for (i=0 ; i<size ; i++)
blocklights[i] += src[i] * scale;
src += size; // skip to next lightmap src += size; // skip to next lightmap
} }
break; break;
@ -1902,7 +1892,7 @@ static void Surf_BuildLightMap_Worker (model_t *wmodel, msurface_t *surf, int sh
} }
} }
Surf_StoreLightmap_Grey(dest, blocklights, smax, tmax, shift, stainsrc, lm->width); Surf_StoreLightmap_Lum(dest, blocklights, smax, tmax, shift, stainsrc, lm->width);
} }
//make sure we flag the output rect properly. //make sure we flag the output rect properly.
@ -1965,7 +1955,7 @@ void Surf_RenderDynamicLightmaps (msurface_t *fa)
} }
else else
{ {
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && fa->styles[maps] != INVALID_LIGHTSTYLE ; for (maps = 0 ; maps < MAXCPULIGHTMAPS && fa->styles[maps] != INVALID_LIGHTSTYLE ;
maps++) maps++)
if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps] if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps]
|| cl_lightstyle[fa->styles[maps]].colourkey != fa->cached_colour[maps]) || cl_lightstyle[fa->styles[maps]].colourkey != fa->cached_colour[maps])
@ -2008,7 +1998,7 @@ static void Surf_RenderDynamicLightmaps_Worker (model_t *wmodel, msurface_t *fa,
} }
else else
{ {
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && fa->styles[maps] != INVALID_LIGHTSTYLE ; for (maps = 0 ; maps < MAXCPULIGHTMAPS && fa->styles[maps] != INVALID_LIGHTSTYLE ;
maps++) maps++)
if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps] if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps]
|| cl_lightstyle[fa->styles[maps]].colourkey != fa->cached_colour[maps]) || cl_lightstyle[fa->styles[maps]].colourkey != fa->cached_colour[maps])

View file

@ -129,7 +129,7 @@ typedef struct entity_s
// only used for static objects // only used for static objects
// int dlightframe; // dynamic lighting // int dlightframe; // dynamic lighting
// int dlightbits; // dlightbitmask_t dlightbits;
// FIXME: could turn these into a union // FIXME: could turn these into a union
// int trivial_accept; // int trivial_accept;

View file

@ -683,11 +683,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
qboolean srcrel; qboolean srcrel;
if (chnum >= oali->max_sources) if (chnum >= oali->max_sources)
{
size_t oc = oali->max_sources;
Z_ReallocElements((void**)&oali->source, &oali->max_sources, chnum+1+64, sizeof(*oali->source)); Z_ReallocElements((void**)&oali->source, &oali->max_sources, chnum+1+64, sizeof(*oali->source));
memset(oali->source+oc, 0, sizeof(*oali->source)*(oali->max_sources-oc));
}
//alcMakeContextCurrent //alcMakeContextCurrent
@ -696,7 +692,6 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
sfx = NULL; sfx = NULL;
#endif #endif
src = oali->source[chnum].handle;
if (!oali->source[chnum].allocated) if (!oali->source[chnum].allocated)
{ {
//not currently playing. be prepared to create one //not currently playing. be prepared to create one
@ -722,58 +717,54 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
oali->source[chnum].allocated = true; oali->source[chnum].allocated = true;
schanged |= CUR_EVERYTHING; //should normally be true anyway, but hey schanged |= CUR_EVERYTHING; //should normally be true anyway, but hey
} }
else
src = oali->source[chnum].handle;
PrintALError("pre start sound"); PrintALError("pre start sound");
if ((schanged&CUR_SOUNDCHANGE) && src) if (schanged&CUR_SOUNDCHANGE)
palSourceStop(src); palSourceStop(src);
//reclaim any queued buffers //reclaim any queued buffers
if (src) palGetSourcei(src, AL_SOURCE_TYPE, &buf);
if (buf == AL_STREAMING)
{ {
palGetSourcei(src, AL_SOURCE_TYPE, &buf); for(;;)
if (buf == AL_STREAMING)
{ {
for(;;) palGetSourcei(src, AL_BUFFERS_PROCESSED, &buf);
{ if (!buf)
palGetSourcei(src, AL_BUFFERS_PROCESSED, &buf); break;
if (!buf) palSourceUnqueueBuffers(src, 1, &buf);
break; palDeleteBuffers(1, &buf);
palSourceUnqueueBuffers(src, 1, &buf);
palDeleteBuffers(1, &buf);
}
} }
else if (!schanged && sfx) //if we don't figure out when they've finished, they'll not get replaced properly. }
else if (!schanged && sfx) //if we don't figure out when they've finished, they'll not get replaced properly.
{
palGetSourcei(src, AL_SOURCE_STATE, &buf);
if (buf != AL_PLAYING)
{ {
palGetSourcei(src, AL_SOURCE_STATE, &buf); schanged |= CUR_EVERYTHING;
if (buf != AL_PLAYING) if(sfx->loopstart != -1)
{ chan->pos = sfx->loopstart<<PITCHSHIFT;
schanged |= CUR_EVERYTHING; else if (chan->flags & CF_FORCELOOP)
if(sfx->loopstart != -1) chan->pos = 0;
chan->pos = sfx->loopstart<<PITCHSHIFT; else
else if (chan->flags & CF_FORCELOOP) sfx = chan->sfx = NULL;
chan->pos = 0;
else
sfx = chan->sfx = NULL;
}
} }
} }
/*just wanted to stop it?*/ /*just wanted to stop it?*/
if (!sfx) if (!sfx)
{ {
if (src)
{
#ifdef FTE_TARGET_WEB #ifdef FTE_TARGET_WEB
//emscripten's webaudio wrapper spams error messages after alDeleteSources has been called, if the context isn't also killed. //emscripten's webaudio wrapper spams error messages after alDeleteSources has been called, if the context isn't also killed.
if (!schanged) if (!schanged)
palSourceStop(src); palSourceStop(src);
#else #else
palDeleteSources(1, &src); palDeleteSources(1, &src);
oali->source[chnum].handle = 0; oali->source[chnum].handle = 0;
oali->source[chnum].allocated = false; oali->source[chnum].allocated = false;
#endif #endif
}
return; return;
} }
@ -791,11 +782,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
int sndnum = sfx-known_sfx; int sndnum = sfx-known_sfx;
int buf; int buf;
if (sndnum >= oali->max_sounds) if (sndnum >= oali->max_sounds)
{
size_t oc = oali->max_sounds;
Z_ReallocElements((void**)&oali->sounds, &oali->max_sounds, sndnum+1+64, sizeof(*oali->sounds)); Z_ReallocElements((void**)&oali->sounds, &oali->max_sounds, sndnum+1+64, sizeof(*oali->sounds));
memset(oali->sounds+oc, 0, sizeof(*oali->sounds)*(oali->max_sounds-oc));
}
buf = oali->sounds[sndnum].buffer; buf = oali->sounds[sndnum].buffer;
if (!oali->sounds[sndnum].allocated || stream) if (!oali->sounds[sndnum].allocated || stream)
{ {
@ -852,8 +839,8 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
{ {
//build a buffer with it and queue it up. //build a buffer with it and queue it up.
//buffer will be purged later on when its unqueued //buffer will be purged later on when its unqueued
OpenAL_LoadCache(oali, &buf, &sbuf, max(1,cvolume)); if (OpenAL_LoadCache(oali, &buf, &sbuf, max(1,cvolume)))
palSourceQueueBuffers(src, 1, &buf); palSourceQueueBuffers(src, 1, &buf);
} }
else else
{ //decoder isn't ready yet, but didn't signal an error/eof. queue a little silence, because that's better than constant micro stutters { //decoder isn't ready yet, but didn't signal an error/eof. queue a little silence, because that's better than constant micro stutters
@ -864,8 +851,8 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
silence.data = NULL; silence.data = NULL;
silence.length = 0.1 * silence.speed; silence.length = 0.1 * silence.speed;
silence.soundoffset = 0; silence.soundoffset = 0;
OpenAL_LoadCache(oali, &buf, &silence, 1); if (OpenAL_LoadCache(oali, &buf, &silence, 1))
palSourceQueueBuffers(src, 1, &buf); palSourceQueueBuffers(src, 1, &buf);
} }
queuedbufs++; queuedbufs++;
@ -893,8 +880,8 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, chanupdat
silence.data = NULL; silence.data = NULL;
silence.length = 0.1 * silence.speed; silence.length = 0.1 * silence.speed;
silence.soundoffset = 0; silence.soundoffset = 0;
OpenAL_LoadCache(oali, &buf, &silence, 1); if (OpenAL_LoadCache(oali, &buf, &silence, 1))
palSourceQueueBuffers(src, 1, &buf); palSourceQueueBuffers(src, 1, &buf);
queuedbufs++; queuedbufs++;
} }
} }

View file

@ -62,6 +62,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif #endif
#include "quakedef.h" #include "quakedef.h"
#include "netinc.h"
#undef malloc #undef malloc
@ -946,6 +947,46 @@ char *Sys_ConsoleInput(void)
return NULL; return NULL;
} }
#ifdef HAVE_GNUTLS
static void DoSign(const char *fname)
{
qbyte digest[1024];
qbyte signature[2048];
qbyte base64[2048*4];
int sigsize;
vfsfile_t *f;
const char *auth = "Unknown";
int i = COM_CheckParm("-certhost");
if (i)
auth = com_argv[i+1];
f = FS_OpenVFS(fname, "rb", FS_SYSTEM);
if (f)
{
hashfunc_t *h = &hash_sha512;
size_t l, ts = 0;
void *ctx = alloca(h->contextsize);
qbyte data[65536*16];
h->init(ctx);
while ((l=VFS_READ(f, data, sizeof(data)))>0)
{
h->process(ctx, data, l);
ts += l;
}
h->terminate(digest, ctx);
VFS_CLOSE(f);
printf(" \\\"dlsize=%zu\\\"", ts);
Base16_EncodeBlock(digest, h->digestsize, base64, sizeof(base64));
printf(" \\\"sha512=%s\\\"", base64);
sigsize = GNUTLS_GenerateSignature(digest, h->digestsize, signature, sizeof(signature));
Base64_EncodeBlock(signature, sigsize, base64, sizeof(base64));
printf(" \\\"sign=%s:%s\\\"\n", auth, base64);
}
}
#endif
#ifdef _POSIX_C_SOURCE #ifdef _POSIX_C_SOURCE
static void SigCont(int code) static void SigCont(int code)
{ {
@ -1029,15 +1070,19 @@ int main (int c, const char **v)
memset(bindir, 0, sizeof(bindir)); //readlink does NOT null terminate, apparently. memset(bindir, 0, sizeof(bindir)); //readlink does NOT null terminate, apparently.
#ifdef __linux__ #ifdef __linux__
//attempt to figure out where the exe is located //attempt to figure out where the exe is located
if (readlink("/proc/self/exe", bindir, sizeof(bindir)-1) > 0) i = readlink("/proc/self/exe", bindir, sizeof(bindir)-1);
if (i > 0)
{ {
bindir[i] = 0;
*COM_SkipPath(bindir) = 0; *COM_SkipPath(bindir) = 0;
parms.binarydir = bindir; parms.binarydir = bindir;
} }
/*#elif defined(__bsd__) /*#elif defined(__bsd__)
//attempt to figure out where the exe is located //attempt to figure out where the exe is located
if (readlink("/proc/self/file", bindir, sizeof(bindir)-1) > 0) i = readlink("/proc/self/file", bindir, sizeof(bindir)-1);
if (i > 0)
{ {
bindir[i] = 0;
*COM_SkipPath(bindir) = 0; *COM_SkipPath(bindir) = 0;
parms.binarydir = bindir; parms.binarydir = bindir;
} }
@ -1066,6 +1111,22 @@ int main (int c, const char **v)
if (COM_CheckParm("-nostdout")) if (COM_CheckParm("-nostdout"))
nostdout = 1; nostdout = 1;
#ifdef HAVE_GNUTLS
//fteqw -privcert privcert.key -pubcert pubcert.key -sign binaryfile.pk3
i = COM_CheckParm("-sign");
if (i)
{
//init some useless crap
host_parms = parms;
Cvar_Init();
Memory_Init ();
COM_Init ();
DoSign(com_argv[i+1]);
return EXIT_SUCCESS;
}
#endif
if (parms.binarydir) if (parms.binarydir)
Sys_Printf("Binary is located at \"%s\"\n", bindir); Sys_Printf("Binary is located at \"%s\"\n", bindir);
@ -1088,7 +1149,6 @@ int main (int c, const char **v)
} }
#endif #endif
Host_Init(&parms); Host_Init(&parms);
for (i = 1; i < parms.argc; i++) for (i = 1; i < parms.argc; i++)
@ -1230,4 +1290,3 @@ qboolean Sys_RunInstaller(void)
return false; return false;
} }
#endif #endif

View file

@ -2883,15 +2883,18 @@ qboolean Sys_EngineMayUpdate(void)
{ {
char *e; char *e;
//no revision info in this build, meaning its custom built and thus cannot check against the available updated versions. if (!COM_CheckParm("-allowupdate"))
if (!strcmp(SVNREVISIONSTR, "-")) {
return false; //no revision info in this build, meaning its custom built and thus cannot check against the available updated versions.
if (!strcmp(SVNREVISIONSTR, "-"))
return false;
//svn revision didn't parse as an exact number. this implies it has an 'M' in it to mark it as modified. //svn revision didn't parse as an exact number. this implies it has an 'M' in it to mark it as modified.
//either way, its bad and autoupdates when we don't know what we're updating from is a bad idea. //either way, its bad and autoupdates when we don't know what we're updating from is a bad idea.
strtoul(SVNREVISIONSTR, &e, 10); strtoul(SVNREVISIONSTR, &e, 10);
if (!*SVNREVISIONSTR || *e) if (!*SVNREVISIONSTR || *e)
return false; return false;
}
//update blocked via commandline //update blocked via commandline
if (COM_CheckParm("-noupdate") || COM_CheckParm("--noupdate") || COM_CheckParm("-noautoupdate") || COM_CheckParm("--noautoupdate")) if (COM_CheckParm("-noupdate") || COM_CheckParm("--noupdate") || COM_CheckParm("-noautoupdate") || COM_CheckParm("--noautoupdate"))

View file

@ -503,7 +503,7 @@ void Validation_FileLoaded(const char *filename, const qbyte *filedata, size_t f
{ {
if (!strcmp(filename, modifiles[i].name) && (modifiles[i].flags & (cl.teamfortress?FMOD_TF:FMOD_DM))) if (!strcmp(filename, modifiles[i].name) && (modifiles[i].flags & (cl.teamfortress?FMOD_TF:FMOD_DM)))
{ {
SHA1(digest, sizeof(digest), filedata, filesize); CalcHash(&hash_sha1, digest, sizeof(digest), filedata, filesize);
for (j = 0; j < modifiles[i].hashes; j++) for (j = 0; j < modifiles[i].hashes; j++)
{ {

View file

@ -2193,7 +2193,7 @@ void R_DrawNameTags(void)
if (Matrix4x4_CM_Project(org, screenspace, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y)) if (Matrix4x4_CM_Project(org, screenspace, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y))
{ {
char asciibuffer[8192]; char asciibuffer[8192];
char *entstr; const char *entstr;
size_t buflen; size_t buflen;
int x, y; int x, y;
@ -2205,7 +2205,19 @@ void R_DrawNameTags(void)
vec2_t scale = {8,8}; vec2_t scale = {8,8};
x = screenspace[0]*r_refdef.vrect.width+r_refdef.vrect.x; x = screenspace[0]*r_refdef.vrect.width+r_refdef.vrect.x;
y = (1-screenspace[1])*r_refdef.vrect.height+r_refdef.vrect.y; y = (1-screenspace[1])*r_refdef.vrect.height+r_refdef.vrect.y;
R_DrawTextField(x, y, vid.width - x, vid.height - y, entstr, CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_console, scale); y += scale[1]*R_DrawTextField(x, y, vid.width - x, vid.height - y, entstr, CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_console, scale);
#ifdef CSQC_DAT
{
extern world_t csqc_world;
if (w == &csqc_world)
{
entstr = CSQC_GetExtraFieldInfo(e, asciibuffer, sizeof(asciibuffer));
if (entstr)
y += scale[1]*R_DrawTextField(x, y, vid.width - x, vid.height - y, entstr, CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_console, scale);
}
}
#endif
} }
} }
} }

View file

@ -839,8 +839,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAX_BACKBUFLEN 1200 #define MAX_BACKBUFLEN 1200
#ifdef Q1BSPS
#define lightstyleindex_t unsigned short #define lightstyleindex_t unsigned short
#else
#define lightstyleindex_t qbyte
#endif
#define INVALID_LIGHTSTYLE ((lightstyleindex_t)(~0u)) //the style that's invalid, signifying to stop adding more. #define INVALID_LIGHTSTYLE ((lightstyleindex_t)(~0u)) //the style that's invalid, signifying to stop adding more.
#define INVALID_VLIGHTSTYLE ((qbyte)(~0u)) //the style that's invalid for verticies, signifying to stop adding more.
// //
// per-level limits // per-level limits

View file

@ -24,6 +24,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAX_MAP_HULLSDQ1 4 #define MAX_MAP_HULLSDQ1 4
#define MAX_MAP_HULLSDH2 8 #define MAX_MAP_HULLSDH2 8
#define MAX_MAP_HULLSM 8 #define MAX_MAP_HULLSM 8
#define RBSP_STYLESPERSURF 4
#define Q1Q2BSP_STYLESPERSURF 4
#ifdef Q1BSPS
#define MAXCPULIGHTMAPS 16 //max lightmaps mixed by the cpu (vanilla q1bsp=4, fte extensions=no real cap, must be >=MAXRLIGHTMAPS)
#elif defined(Q1BSPS)
#define MAXCPULIGHTMAPS Q1Q2BSP_STYLESPERSURF //max lightmaps mixed by the cpu (vanilla q1bsp=4, fte extensions=no real cap, must be >=MAXRLIGHTMAPS)
#else
#define MAXCPULIGHTMAPS MAXRLIGHTMAPS //max lightmaps mixed by the cpu (vanilla q1bsp=4, fte extensions=no real cap, must be >=MAXRLIGHTMAPS)
#endif
//#define MAX_MAP_MODELS 256 //#define MAX_MAP_MODELS 256
//#define MAX_MAP_BRUSHES 0x8000 //#define MAX_MAP_BRUSHES 0x8000
@ -235,11 +244,10 @@ typedef struct
} dledge_t; } dledge_t;
#ifdef RFBSPS #ifdef RFBSPS
#define MAXRLIGHTMAPS 4 //max lightmaps mixed by the renderer (rbsp=4, otherwise 1) #define MAXRLIGHTMAPS 4 //max lightmaps mixed by the gpu (rbsp=4, otherwise 1)
#else #else
#define MAXRLIGHTMAPS 1 //max lightmaps mixed by the renderer (rbsp=4, otherwise 1) #define MAXRLIGHTMAPS 1 //max lightmaps mixed by the gpu (rbsp=4, otherwise 1)
#endif #endif
#define MAXQ1LIGHTMAPS 16
typedef struct typedef struct
{ {
short planenum; short planenum;
@ -250,7 +258,7 @@ typedef struct
short texinfo; short texinfo;
// lighting info // lighting info
qbyte styles[4]; qbyte styles[Q1Q2BSP_STYLESPERSURF];
int lightofs; // start of [numstyles*surfsize] samples int lightofs; // start of [numstyles*surfsize] samples
} dsface_t; } dsface_t;
typedef struct typedef struct
@ -263,7 +271,7 @@ typedef struct
int texinfo; int texinfo;
// lighting info // lighting info
qbyte styles[4]; qbyte styles[Q1Q2BSP_STYLESPERSURF];
int lightofs; // start of [numstyles*surfsize] samples int lightofs; // start of [numstyles*surfsize] samples
} dlface_t; } dlface_t;
@ -821,9 +829,10 @@ typedef struct
typedef struct typedef struct
{ {
float point[3]; float point[3];
float texcoords[5][2]; float stcoords[2];
float lmtexcoords[RBSP_STYLESPERSURF][2];
float normal[3]; float normal[3];
unsigned char color[4][4]; unsigned char color[RBSP_STYLESPERSURF][4];
} rbspvertex_t; } rbspvertex_t;
struct Q3FOG struct Q3FOG
@ -854,8 +863,7 @@ typedef struct
int firstindex; int firstindex;
int num_indexes; int num_indexes;
int lightmapnum; int lightmapnum;
int lightmap_x; int lightmap_offs[2];
int lightmap_y;
int lightmap_width; int lightmap_width;
int lightmap_height; int lightmap_height;
float lightmap_origin[3]; float lightmap_origin[3];
@ -874,10 +882,10 @@ typedef struct
int num_vertices; int num_vertices;
int firstindex; int firstindex;
int num_indexes; int num_indexes;
unsigned char lm_styles[4]; unsigned char lm_styles[RBSP_STYLESPERSURF];
unsigned char vt_styles[4]; unsigned char vt_styles[RBSP_STYLESPERSURF];
int lightmapnum[4]; int lightmapnum[RBSP_STYLESPERSURF];
int lightmap_offs[2][4]; int lightmap_offs[2][RBSP_STYLESPERSURF]; //yes, weird ordering.
int lightmap_width; int lightmap_width;
int lightmap_height; int lightmap_height;
float lightmap_origin[3]; float lightmap_origin[3];

View file

@ -5466,6 +5466,16 @@ const char *Mod_SkinNameForNum(model_t *model, int surfaceidx, int num)
galiasinfo_t *inf; galiasinfo_t *inf;
galiasskin_t *skin; galiasskin_t *skin;
if (!model || model->loadstate != MLS_LOADED)
{
if (model && model->loadstate == MLS_NOTLOADED)
Mod_LoadModel(model, MLV_SILENT);
if (model && model->loadstate == MLS_LOADING)
COM_WorkerPartialSync(model, &model->loadstate, MLS_LOADING);
if (!model || model->loadstate != MLS_LOADED)
return NULL;
}
if (!model || model->type != mod_alias) if (!model || model->type != mod_alias)
{ {
if (model->type == mod_brush && surfaceidx < model->numtextures && !num) if (model->type == mod_brush && surfaceidx < model->numtextures && !num)

View file

@ -6040,6 +6040,97 @@ static int Base64_Decode(char inp)
//if (inp == '=') //padding char //if (inp == '=') //padding char
return 0; //invalid return 0; //invalid
} }
size_t Base64_EncodeBlock(const qbyte *in, size_t length, char *out, size_t outsize)
{
char *start = out;
char *end = out+outsize-1;
unsigned int v;
while(length > 0)
{
v = 0;
if (length > 0)
v |= in[0]<<16;
if (length > 1)
v |= in[1]<<8;
if (length > 2)
v |= in[2]<<0;
if (out < end) *out++ = (length>=1)?Base64_Encode((v>>18)&63):'=';
if (out < end) *out++ = (length>=1)?Base64_Encode((v>>12)&63):'=';
if (out < end) *out++ = (length>=2)?Base64_Encode((v>>6)&63):'=';
if (out < end) *out++ = (length>=3)?Base64_Encode((v>>0)&63):'=';
in+=3;
length -= 3;
}
end++;
if (out < end)
*out = 0;
return out-start;
}
size_t Base64_DecodeBlock(const char *in, const char *in_end, qbyte *out, size_t outsize)
{
qbyte *start = out;
unsigned int v;
if (!in_end)
in_end = in + strlen(in);
if (!out)
return ((in_end-in+3)/4)*3 + 1; //upper estimate, with null terminator for convienience.
for (; outsize > 1;)
{
while(*in > 0 && *in < ' ')
in++;
if (in >= in_end || !*in || outsize < 1)
break; //end of message when EOF, otherwise error
v = Base64_Decode(*in++)<<18;
while(*in > 0 && *in < ' ')
in++;
if (in >= in_end || !*in || outsize < 1)
break; //some kind of error
v |= Base64_Decode(*in++)<<12;
*out++ = (v>>16)&0xff;
if (in >= in_end || *in == '=' || !*in || outsize < 2)
break; //end of message when '=', otherwise error
v |= Base64_Decode(*in++)<<6;
*out++ = (v>>8)&0xff;
if (in >= in_end || *in == '=' || !*in || outsize < 3)
break; //end of message when '=', otherwise error
v |= Base64_Decode(*in++)<<0;
*out++ = (v>>0)&0xff;
outsize -= 3;
}
return out-start; //total written (no null, output is considered binary)
}
size_t Base16_DecodeBlock(const char *in, qbyte *out, size_t outsize)
{
qbyte *start = out;
if (!out)
return ((strlen(in)+1)/2) + 1;
for (; ishexcode(in[0]) && ishexcode(in[1]) && outsize > 0; outsize--, in+=2)
*out++ = (dehex(in[0])<<4) | dehex(in[1]);
return out-start;
}
size_t Base16_EncodeBlock(const char *in, size_t length, qbyte *out, size_t outsize)
{
const char tab[16] = "0123456789abcdef";
qbyte *start = out;
if (!out)
return (length*2) + 1;
if (outsize > length*2)
*out = 0;
while (length --> 0)
{
*out++ = tab[(*in>>4)&0xf];
*out++ = tab[(*in>>0)&0xf];
in++;
}
return out-start;
}
/* /*
Info Buffers Info Buffers
*/ */

View file

@ -742,7 +742,7 @@ char *FS_GetManifestArgs(void);
int FS_GetManifestArgv(char **argv, int maxargs); int FS_GetManifestArgv(char **argv, int maxargs);
struct zonegroup_s; struct zonegroup_s;
void *FS_LoadMallocGroupFile(struct zonegroup_s *ctx, char *path, size_t *fsize); void *FS_LoadMallocGroupFile(struct zonegroup_s *ctx, char *path, size_t *fsize, qboolean filters);
qbyte *FS_LoadMallocFile (const char *path, size_t *fsize); qbyte *FS_LoadMallocFile (const char *path, size_t *fsize);
qofs_t FS_LoadFile(const char *name, void **file); qofs_t FS_LoadFile(const char *name, void **file);
void FS_FreeFile(void *file); void FS_FreeFile(void *file);
@ -848,13 +848,26 @@ qbyte COM_BlockSequenceCheckByte (qbyte *base, int length, int sequence, unsigne
qbyte COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence); qbyte COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence);
qbyte Q2COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence); qbyte Q2COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence);
typedef size_t hashfunc_t(unsigned char *digest, size_t maxdigestsize, size_t numstrings, const unsigned char **strings, size_t *stringlens); size_t Base64_EncodeBlock(const qbyte *in, size_t length, char *out, size_t outsize); //tries to null terminate, but returns length without termination.
#define SHA1 SHA1_quake size_t Base64_DecodeBlock(const char *in, const char *in_end, qbyte *out, size_t outsize); // +/ and =
#define HMAC HMAC_quake size_t Base16_EncodeBlock(const char *in, size_t length, qbyte *out, size_t outsize);
hashfunc_t SHA1_m; size_t Base16_DecodeBlock(const char *in, qbyte *out, size_t outsize);
//int SHA1_m(char *digest, size_t maxdigestsize, size_t numstrings, const char **strings, size_t *stringlens);
//#define SHA1(digest,maxdigestsize,string,stringlen) SHA1_m(digest, maxdigestsize, 1, &string, &stringlen) typedef struct
size_t SHA1(unsigned char *digest, size_t maxdigestsize, const unsigned char *string, size_t stringlen); {
unsigned int digestsize;
unsigned int contextsize; //you need to alloca(te) this much memory...
void (*init) (void *context);
void (*process) (void *context, const void *data, size_t datasize);
void (*terminate) (unsigned char *digest, void *context);
} hashfunc_t;
extern hashfunc_t hash_sha1;
extern hashfunc_t hash_sha224;
extern hashfunc_t hash_sha256;
extern hashfunc_t hash_sha384;
extern hashfunc_t hash_sha512;
#define HMAC HMAC_quake //stop conflicts...
size_t CalcHash(hashfunc_t *hash, unsigned char *digest, size_t maxdigestsize, const unsigned char *string, size_t stringlen);
size_t HMAC(hashfunc_t *hashfunc, unsigned char *digest, size_t maxdigestsize, const unsigned char *data, size_t datalen, const unsigned char *key, size_t keylen); size_t HMAC(hashfunc_t *hashfunc, unsigned char *digest, size_t maxdigestsize, const unsigned char *data, size_t datalen, const unsigned char *key, size_t keylen);
int version_number(void); int version_number(void);

View file

@ -1824,7 +1824,7 @@ static vfsfile_t *VFS_Filter(const char *filename, vfsfile_t *handle)
{ {
// char *ext; // char *ext;
if (!handle || handle->WriteBytes || handle->seekstyle == SS_SLOW || handle->seekstyle == SS_UNSEEKABLE) //only on readonly files for which we can undo any header read damage if (!handle || !handle->ReadBytes || handle->seekstyle == SS_SLOW || handle->seekstyle == SS_UNSEEKABLE) //only on readonly files for which we can undo any header read damage
return handle; return handle;
// ext = COM_FileExtension (filename); // ext = COM_FileExtension (filename);
#ifdef AVAIL_GZDEC #ifdef AVAIL_GZDEC
@ -2170,7 +2170,7 @@ vfsfile_t *QDECL FS_OpenVFS(const char *filename, const char *mode, enum fs_rela
if (loc.search) if (loc.search)
{ {
return VFS_Filter(filename, loc.search->handle->OpenVFS(loc.search->handle, &loc, mode)); return loc.search->handle->OpenVFS(loc.search->handle, &loc, mode);
} }
//if we're meant to be writing, best write to it. //if we're meant to be writing, best write to it.
@ -2406,14 +2406,19 @@ qbyte *FS_LoadMallocFile (const char *path, size_t *fsize)
return COM_LoadFile (path, 0, 5, fsize); return COM_LoadFile (path, 0, 5, fsize);
} }
void *FS_LoadMallocGroupFile(zonegroup_t *ctx, char *path, size_t *fsize) void *FS_LoadMallocGroupFile(zonegroup_t *ctx, char *path, size_t *fsize, qboolean filters)
{ {
char *mem = NULL; char *mem = NULL;
vfsfile_t *f = FS_OpenVFS(path, "rb", FS_GAME); vfsfile_t *f = FS_OpenVFS(path, "rb", FS_GAME);
if (f && filters)
f = VFS_Filter(path, f);
if (f) if (f)
{ {
int len = VFS_GETLEN(f); int len = VFS_GETLEN(f);
mem = ZG_Malloc(ctx, len+1); if (ctx)
mem = ZG_Malloc(ctx, len+1);
else
mem = BZ_Malloc(len+1);
if (mem) if (mem)
{ {
mem[len] = 0; mem[len] = 0;

View file

@ -38,6 +38,7 @@
cvar_t q3bsp_surf_meshcollision_flag = CVARD("q3bsp_surf_meshcollision_flag", "0x80000000", "The surfaceparm flag(s) that enables q3bsp trisoup collision"); cvar_t q3bsp_surf_meshcollision_flag = CVARD("q3bsp_surf_meshcollision_flag", "0x80000000", "The surfaceparm flag(s) that enables q3bsp trisoup collision");
cvar_t q3bsp_surf_meshcollision_force = CVARD("q3bsp_surf_meshcollision_force", "0", "Force mesh-based collisions on all q3bsp trisoup surfaces."); cvar_t q3bsp_surf_meshcollision_force = CVARD("q3bsp_surf_meshcollision_force", "0", "Force mesh-based collisions on all q3bsp trisoup surfaces.");
cvar_t q3bsp_mergeq3lightmaps = CVARD("q3bsp_mergelightmaps", "1", "Specifies whether to merge lightmaps into atlases in order to boost performance. Unfortunately this breaks tcgen on lightmap passes - if you care, set this to 0."); cvar_t q3bsp_mergeq3lightmaps = CVARD("q3bsp_mergelightmaps", "1", "Specifies whether to merge lightmaps into atlases in order to boost performance. Unfortunately this breaks tcgen on lightmap passes - if you care, set this to 0.");
cvar_t q3bsp_ignorestyles = CVARD("q3bsp_ignorestyles", "0", "Ignores multiple lightstyles in Raven's q3bsp variant(and derivatives) for better batch/rendering performance.");
cvar_t q3bsp_bihtraces = CVARFD("_q3bsp_bihtraces", "0", CVAR_RENDERERLATCH, "Uses runtime-generated bih collision culling for faster traces."); cvar_t q3bsp_bihtraces = CVARFD("_q3bsp_bihtraces", "0", CVAR_RENDERERLATCH, "Uses runtime-generated bih collision culling for faster traces.");
#if Q3SURF_NODRAW != TI_NODRAW #if Q3SURF_NODRAW != TI_NODRAW
@ -1696,7 +1697,7 @@ static qboolean CModQ2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l, lump
out->styles[i] = style; out->styles[i] = style;
} }
} }
for ( ; i<MAXQ1LIGHTMAPS ; i++) for ( ; i<MAXCPULIGHTMAPS ; i++)
out->styles[i] = INVALID_LIGHTSTYLE; out->styles[i] = INVALID_LIGHTSTYLE;
if (overrides.offsets) if (overrides.offsets)
i = overrides.offsets[surfnum]; i = overrides.offsets[surfnum];
@ -2476,11 +2477,11 @@ static qboolean CModRBSP_LoadVertexes (model_t *mod, qbyte *mod_base, lump_t *l)
} }
for ( j=0 ; j < 2 ; j++) for ( j=0 ; j < 2 ; j++)
{ {
stout[i][j] = LittleFloat ( ((float *)in->texcoords)[j] ); stout[i][j] = LittleFloat (in->stcoords[j]);
for (sty = 0; sty < MAXRLIGHTMAPS; sty++) for (sty = 0; sty < min(MAXRLIGHTMAPS, RBSP_STYLESPERSURF); sty++)
prv->vertlstmexcoords[sty][i][j] = LittleFloat ( ((float *)in->texcoords)[j+2*(sty+1)] ); prv->vertlstmexcoords[sty][i][j] = LittleFloat(in->lmtexcoords[sty][j]);
} }
for (sty = 0; sty < MAXRLIGHTMAPS; sty++) for (sty = 0; sty < min(MAXRLIGHTMAPS, RBSP_STYLESPERSURF); sty++)
{ {
prv->colors4f_array[sty][i][0] = lmgamma[in->color[sty][0]]/255.0f; prv->colors4f_array[sty][i][0] = lmgamma[in->color[sty][0]]/255.0f;
prv->colors4f_array[sty][i][1] = lmgamma[in->color[sty][1]]/255.0f; prv->colors4f_array[sty][i][1] = lmgamma[in->color[sty][1]]/255.0f;
@ -3203,17 +3204,17 @@ static qboolean CModQ3_LoadRFaces (model_t *mod, qbyte *mod_base, lump_t *l)
else if (out->lightmaptexturenums[0] < 0 /*|| facetype == MST_TRIANGLE_SOUP*/ || r_vertexlight.value) else if (out->lightmaptexturenums[0] < 0 /*|| facetype == MST_TRIANGLE_SOUP*/ || r_vertexlight.value)
out->texinfo += mod->numtexinfo; //various surfaces use a different version of the same shader (with all the lightmaps collapsed) out->texinfo += mod->numtexinfo; //various surfaces use a different version of the same shader (with all the lightmaps collapsed)
out->light_s[0] = LittleLong(in->lightmap_x); out->light_s[0] = LittleLong(in->lightmap_offs[0]);
out->light_t[0] = LittleLong(in->lightmap_y); out->light_t[0] = LittleLong(in->lightmap_offs[1]);
out->styles[0] = INVALID_LIGHTSTYLE; out->styles[0] = INVALID_LIGHTSTYLE;
out->vlstyles[0] = 255; out->vlstyles[0] = INVALID_VLIGHTSTYLE;
for (sty = 1; sty < MAXRLIGHTMAPS; sty++) for (sty = 1; sty < MAXRLIGHTMAPS; sty++)
{ {
out->styles[sty] = INVALID_LIGHTSTYLE; out->styles[sty] = INVALID_LIGHTSTYLE;
out->vlstyles[sty] = 255; out->vlstyles[sty] = INVALID_VLIGHTSTYLE;
out->lightmaptexturenums[sty] = -1; out->lightmaptexturenums[sty] = -1;
} }
for (; sty < MAXQ1LIGHTMAPS; sty++) for (; sty < MAXCPULIGHTMAPS; sty++)
out->styles[sty] = INVALID_LIGHTSTYLE; out->styles[sty] = INVALID_LIGHTSTYLE;
out->lmshift = LMSHIFT_DEFAULT; out->lmshift = LMSHIFT_DEFAULT;
//fixme: determine texturemins from lightmap_origin //fixme: determine texturemins from lightmap_origin
@ -3300,6 +3301,8 @@ static qboolean CModRBSP_LoadRFaces (model_t *mod, qbyte *mod_base, lump_t *l)
mesh_t *mesh; mesh_t *mesh;
int maxstyle = q3bsp_ignorestyles.ival?1:min(MAXRLIGHTMAPS, RBSP_STYLESPERSURF);
in = (void *)(mod_base + l->fileofs); in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in)) if (l->filelen % sizeof(*in))
@ -3320,18 +3323,26 @@ static qboolean CModRBSP_LoadRFaces (model_t *mod, qbyte *mod_base, lump_t *l)
out->plane = pl; out->plane = pl;
facetype = LittleLong(in->facetype); facetype = LittleLong(in->facetype);
out->texinfo = mod->texinfo + LittleLong(in->shadernum); out->texinfo = mod->texinfo + LittleLong(in->shadernum);
for (j = 0; j < 4 && j < MAXRLIGHTMAPS; j++) for (j = 0; j < maxstyle; j++)
{ {
out->lightmaptexturenums[j] = LittleLong(in->lightmapnum[j]); out->lightmaptexturenums[j] = LittleLong(in->lightmapnum[j]);
out->light_s[j] = LittleLong(in->lightmap_offs[0][j]); out->light_s[j] = LittleLong(in->lightmap_offs[0][j]);
out->light_t[j] = LittleLong(in->lightmap_offs[1][j]); out->light_t[j] = LittleLong(in->lightmap_offs[1][j]);
out->styles[j] = (in->lm_styles[j]!=255)?in->lm_styles[j]:INVALID_LIGHTSTYLE; out->styles[j] = (in->lm_styles[j]!=255)?in->lm_styles[j]:INVALID_LIGHTSTYLE;
out->vlstyles[j] = in->vt_styles[j]; out->vlstyles[j] = (in->vt_styles[j]!=255)?in->vt_styles[j]:INVALID_VLIGHTSTYLE;
if (mod->lightmaps.count < out->lightmaptexturenums[j]+1) if (mod->lightmaps.count < out->lightmaptexturenums[j]+1)
mod->lightmaps.count = out->lightmaptexturenums[j]+1; mod->lightmaps.count = out->lightmaptexturenums[j]+1;
} }
for (; j < MAXQ1LIGHTMAPS; j++) for (; j < MAXRLIGHTMAPS; j++)
{
out->lightmaptexturenums[j] = -1;
out->light_s[j] = 0;
out->light_t[j] = 0;
out->styles[j] = INVALID_LIGHTSTYLE;
out->vlstyles[j] = INVALID_VLIGHTSTYLE;
}
for (; j < MAXCPULIGHTMAPS; j++)
out->styles[j] = INVALID_LIGHTSTYLE; out->styles[j] = INVALID_LIGHTSTYLE;
if (facetype == MST_FLARE) if (facetype == MST_FLARE)
out->texinfo = mod->texinfo + mod->numtexinfo*2; out->texinfo = mod->texinfo + mod->numtexinfo*2;
@ -4217,7 +4228,7 @@ static qbyte *CM_LeafnumPVS (model_t *model, int leafnum, qbyte *buffer, unsigne
#define GLQ2BSP_LightPointValues GLQ1BSP_LightPointValues #define GLQ2BSP_LightPointValues GLQ1BSP_LightPointValues
extern int r_dlightframecount; extern int r_dlightframecount;
static void Q2BSP_MarkLights (dlight_t *light, int bit, mnode_t *node) static void Q2BSP_MarkLights (dlight_t *light, dlightbitmask_t bit, mnode_t *node)
{ {
mplane_t *splitplane; mplane_t *splitplane;
float dist; float dist;
@ -4264,7 +4275,7 @@ static void Q2BSP_MarkLights (dlight_t *light, int bit, mnode_t *node)
{ {
if (surf->dlightframe != r_dlightframecount) if (surf->dlightframe != r_dlightframecount)
{ {
surf->dlightbits = 0; surf->dlightbits = 0u;
surf->dlightframe = r_dlightframecount; surf->dlightframe = r_dlightframecount;
} }
surf->dlightbits |= bit; surf->dlightbits |= bit;
@ -4322,18 +4333,18 @@ CM_LoadMap
Loads in the map and all submodels Loads in the map and all submodels
================== ==================
*/ */
static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboolean clientload, unsigned *checksum) static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboolean clientload)
{ {
unsigned *buf; unsigned *buf;
int i; int i;
q2dheader_t header; q2dheader_t header;
int length; int length;
static unsigned last_checksum;
qboolean noerrors = true; qboolean noerrors = true;
model_t *wmod = mod; model_t *wmod = mod;
char loadname[32]; char loadname[32];
qbyte *mod_base = (qbyte *)filein; qbyte *mod_base = (qbyte *)filein;
bspx_header_t *bspx = NULL; bspx_header_t *bspx = NULL;
unsigned int checksum;
#ifdef Q3BSPS #ifdef Q3BSPS
extern cvar_t gl_overbright; extern cvar_t gl_overbright;
#endif #endif
@ -4360,7 +4371,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
mod->leafs = ZG_Malloc(&mod->memgroup, 1 * sizeof(*mod->leafs)); mod->leafs = ZG_Malloc(&mod->memgroup, 1 * sizeof(*mod->leafs));
prv->numcmodels = 1; prv->numcmodels = 1;
prv->numareas = 1; prv->numareas = 1;
*checksum = 0; mod->checksum = mod->checksum2 = 0;
prv->cmodels[0].headnode = (mnode_t*)mod->leafs; //directly start with the empty leaf prv->cmodels[0].headnode = (mnode_t*)mod->leafs; //directly start with the empty leaf
return &prv->cmodels[0]; // cinematic servers won't have anything at all return &prv->cmodels[0]; // cinematic servers won't have anything at all
} }
@ -4376,8 +4387,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
return NULL; return NULL;
} }
last_checksum = LittleLong (Com_BlockChecksum (buf, length)); checksum = LittleLong (Com_BlockChecksum (buf, length));
*checksum = last_checksum;
header = *(q2dheader_t *)(buf); header = *(q2dheader_t *)(buf);
header.ident = LittleLong(header.ident); header.ident = LittleLong(header.ident);
@ -4775,7 +4785,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
#endif #endif
FloodAreaConnections (prv); FloodAreaConnections (prv);
mod->checksum = mod->checksum2 = *checksum; mod->checksum = mod->checksum2 = checksum;
mod->nummodelsurfaces = mod->numsurfaces; mod->nummodelsurfaces = mod->numsurfaces;
memset(&mod->batches, 0, sizeof(mod->batches)); memset(&mod->batches, 0, sizeof(mod->batches));
@ -7702,11 +7712,10 @@ unsigned int Q2BSP_PointContents(model_t *mod, const vec3_t axis[3], const vec3_
int map_checksum;
qboolean QDECL Mod_LoadQ2BrushModel (model_t *mod, void *buffer, size_t fsize) qboolean QDECL Mod_LoadQ2BrushModel (model_t *mod, void *buffer, size_t fsize)
{ {
mod->fromgame = fg_quake2; mod->fromgame = fg_quake2;
return CM_LoadMap(mod, buffer, fsize, true, &map_checksum) != NULL; return CM_LoadMap(mod, buffer, fsize, true) != NULL;
} }
void CM_Init(void) //register cvars. void CM_Init(void) //register cvars.
@ -7718,6 +7727,7 @@ void CM_Init(void) //register cvars.
Cvar_Register(&q3bsp_surf_meshcollision_flag, MAPOPTIONS); Cvar_Register(&q3bsp_surf_meshcollision_flag, MAPOPTIONS);
Cvar_Register(&q3bsp_surf_meshcollision_force, MAPOPTIONS); Cvar_Register(&q3bsp_surf_meshcollision_force, MAPOPTIONS);
Cvar_Register(&q3bsp_mergeq3lightmaps, MAPOPTIONS); Cvar_Register(&q3bsp_mergeq3lightmaps, MAPOPTIONS);
Cvar_Register(&q3bsp_ignorestyles, MAPOPTIONS);
Cvar_Register(&q3bsp_bihtraces, MAPOPTIONS); Cvar_Register(&q3bsp_bihtraces, MAPOPTIONS);
Cvar_Register(&r_subdivisions, MAPOPTIONS); Cvar_Register(&r_subdivisions, MAPOPTIONS);

View file

@ -93,7 +93,7 @@ typedef struct netadr_s
} address; } address;
unsigned short port; unsigned short port;
unsigned short connum; //which quake connection/socket the address is talking about. 1-based. 0 is unspecified. unsigned short connum; //which quake connection/socket the address is talking about. 1-based. 0 is unspecified. this is NOT used for address equivelency.
unsigned int scopeid; //ipv6 interface id thing. unsigned int scopeid; //ipv6 interface id thing.
} netadr_t; } netadr_t;

View file

@ -477,7 +477,7 @@ static qboolean ICE_SendSpam(struct icestate_s *con)
data[2] = ((buf.cursize+4+sizeof(integ)-20)>>8)&0xff; //hashed header length is up to the end of the hmac attribute data[2] = ((buf.cursize+4+sizeof(integ)-20)>>8)&0xff; //hashed header length is up to the end of the hmac attribute
data[3] = ((buf.cursize+4+sizeof(integ)-20)>>0)&0xff; data[3] = ((buf.cursize+4+sizeof(integ)-20)>>0)&0xff;
//but the hash is to the start of the attribute's header //but the hash is to the start of the attribute's header
HMAC(SHA1_m, integ, sizeof(integ), data, buf.cursize, con->rpwd, strlen(con->rpwd)); HMAC(&hash_sha1, integ, sizeof(integ), data, buf.cursize, con->rpwd, strlen(con->rpwd));
MSG_WriteShort(&buf, BigShort(0x8)); //MESSAGE-INTEGRITY MSG_WriteShort(&buf, BigShort(0x8)); //MESSAGE-INTEGRITY
MSG_WriteShort(&buf, BigShort(20)); //sha1 key length MSG_WriteShort(&buf, BigShort(20)); //sha1 key length
SZ_Write(&buf, integ, sizeof(integ)); //integrity data SZ_Write(&buf, integ, sizeof(integ)); //integrity data
@ -1523,7 +1523,7 @@ qboolean ICE_WasStun(ftenet_connections_t *col)
char key[20]; char key[20];
//the hmac is a bit weird. the header length includes the integrity attribute's length, but the checksum doesn't even consider the attribute header. //the hmac is a bit weird. the header length includes the integrity attribute's length, but the checksum doesn't even consider the attribute header.
stun->msglen = BigShort(integritypos+sizeof(integrity) - (char*)stun - sizeof(*stun)); stun->msglen = BigShort(integritypos+sizeof(integrity) - (char*)stun - sizeof(*stun));
HMAC(SHA1_m, key, sizeof(key), (qbyte*)stun, integritypos-4 - (char*)stun, con->lpwd, strlen(con->lpwd)); HMAC(&hash_sha1, key, sizeof(key), (qbyte*)stun, integritypos-4 - (char*)stun, con->lpwd, strlen(con->lpwd));
if (memcmp(key, integrity, sizeof(integrity))) if (memcmp(key, integrity, sizeof(integrity)))
{ {
Con_DPrintf("Integrity is bad! needed %x got %x\n", *(int*)key, *(int*)integrity); Con_DPrintf("Integrity is bad! needed %x got %x\n", *(int*)key, *(int*)integrity);
@ -1690,7 +1690,7 @@ qboolean ICE_WasStun(ftenet_connections_t *col)
data[2] = ((buf.cursize+4+sizeof(integrity)-20)>>8)&0xff; //hashed header length is up to the end of the hmac attribute data[2] = ((buf.cursize+4+sizeof(integrity)-20)>>8)&0xff; //hashed header length is up to the end of the hmac attribute
data[3] = ((buf.cursize+4+sizeof(integrity)-20)>>0)&0xff; data[3] = ((buf.cursize+4+sizeof(integrity)-20)>>0)&0xff;
//but the hash is to the start of the attribute's header //but the hash is to the start of the attribute's header
HMAC(SHA1_m, integrity, sizeof(integrity), data, buf.cursize, con->lpwd, strlen(con->lpwd)); HMAC(&hash_sha1, integrity, sizeof(integrity), data, buf.cursize, con->lpwd, strlen(con->lpwd));
MSG_WriteShort(&buf, BigShort(0x8)); //MESSAGE-INTEGRITY MSG_WriteShort(&buf, BigShort(0x8)); //MESSAGE-INTEGRITY
MSG_WriteShort(&buf, BigShort(sizeof(integrity))); //sha1 key length MSG_WriteShort(&buf, BigShort(sizeof(integrity))); //sha1 key length
SZ_Write(&buf, integrity, sizeof(integrity)); //integrity data SZ_Write(&buf, integrity, sizeof(integrity)); //integrity data

View file

@ -11,8 +11,6 @@
#endif #endif
#ifdef HAVE_GNUTLS #ifdef HAVE_GNUTLS
#define privname "privkey.pem"
#define pubname "cert.pem"
#if defined(_WIN32) && !defined(MINGW) && 0 #if defined(_WIN32) && !defined(MINGW) && 0
@ -205,6 +203,7 @@ static int (VARGS *qgnutls_x509_crt_set_dn)(gnutls_x509_crt_t crt, const char *
static int (VARGS *qgnutls_x509_crt_set_issuer_dn)(gnutls_x509_crt_t crt, const char *dn, const char **err); static int (VARGS *qgnutls_x509_crt_set_issuer_dn)(gnutls_x509_crt_t crt, const char *dn, const char **err);
static int (VARGS *qgnutls_x509_crt_set_key)(gnutls_x509_crt_t crt, gnutls_x509_privkey_t key); static int (VARGS *qgnutls_x509_crt_set_key)(gnutls_x509_crt_t crt, gnutls_x509_privkey_t key);
static int (VARGS *qgnutls_x509_crt_export2)(gnutls_x509_crt_t cert, gnutls_x509_crt_fmt_t format, gnutls_datum_t * out); static int (VARGS *qgnutls_x509_crt_export2)(gnutls_x509_crt_t cert, gnutls_x509_crt_fmt_t format, gnutls_datum_t * out);
static int (VARGS *qgnutls_x509_crt_import)(gnutls_x509_crt_t cert, const gnutls_datum_t *data, gnutls_x509_crt_fmt_t format);
static int (VARGS *qgnutls_x509_privkey_init)(gnutls_x509_privkey_t * key); static int (VARGS *qgnutls_x509_privkey_init)(gnutls_x509_privkey_t * key);
static void (VARGS *qgnutls_x509_privkey_deinit)(gnutls_x509_privkey_t key); static void (VARGS *qgnutls_x509_privkey_deinit)(gnutls_x509_privkey_t key);
static int (VARGS *qgnutls_x509_privkey_generate)(gnutls_x509_privkey_t key, gnutls_pk_algorithm_t algo, unsigned int bits, unsigned int flags); static int (VARGS *qgnutls_x509_privkey_generate)(gnutls_x509_privkey_t key, gnutls_pk_algorithm_t algo, unsigned int bits, unsigned int flags);
@ -213,7 +212,14 @@ static int (VARGS *qgnutls_x509_crt_privkey_sign)(gnutls_x509_crt_t crt, gnutls
static int (VARGS *qgnutls_privkey_init)(gnutls_privkey_t * key); static int (VARGS *qgnutls_privkey_init)(gnutls_privkey_t * key);
static void (VARGS *qgnutls_privkey_deinit)(gnutls_privkey_t key); static void (VARGS *qgnutls_privkey_deinit)(gnutls_privkey_t key);
static int (VARGS *qgnutls_privkey_import_x509)(gnutls_privkey_t pkey, gnutls_x509_privkey_t key, unsigned int flags); static int (VARGS *qgnutls_privkey_import_x509)(gnutls_privkey_t pkey, gnutls_x509_privkey_t key, unsigned int flags);
//static int (VARGS *qgnutls_privkey_sign_hash2)(gnutls_privkey_t signer, gnutls_sign_algorithm_t algo, unsigned int flags, const gnutls_datum_t * hash_data, gnutls_datum_t * signature);
static int (VARGS *qgnutls_privkey_sign_hash)(gnutls_privkey_t signer, gnutls_digest_algorithm_t hash_algo, unsigned int flags, const gnutls_datum_t * hash_data, gnutls_datum_t * signature);
static int (VARGS *qgnutls_pubkey_init)(gnutls_pubkey_t * key);
static int (VARGS *qgnutls_pubkey_import_x509)(gnutls_pubkey_t key, gnutls_x509_crt_t crt, unsigned int flags);
static int (VARGS *qgnutls_pubkey_verify_hash2)(gnutls_pubkey_t key, gnutls_sign_algorithm_t algo, unsigned int flags, const gnutls_datum_t * hash, const gnutls_datum_t * signature);
static int (VARGS *qgnutls_certificate_set_x509_key_mem)(gnutls_certificate_credentials_t res, const gnutls_datum_t * cert, const gnutls_datum_t * key, gnutls_x509_crt_fmt_t type); static int (VARGS *qgnutls_certificate_set_x509_key_mem)(gnutls_certificate_credentials_t res, const gnutls_datum_t * cert, const gnutls_datum_t * key, gnutls_x509_crt_fmt_t type);
static int (VARGS *qgnutls_certificate_get_x509_key)(gnutls_certificate_credentials_t res, unsigned index, gnutls_x509_privkey_t *key);
static void (VARGS *qgnutls_certificate_free_credentials)(gnutls_certificate_credentials_t sc);
static qboolean Init_GNUTLS(void) static qboolean Init_GNUTLS(void)
{ {
@ -384,6 +390,13 @@ static qboolean Init_GNUTLS(void)
{(void**)&qgnutls_privkey_import_x509, "gnutls_privkey_import_x509"}, {(void**)&qgnutls_privkey_import_x509, "gnutls_privkey_import_x509"},
{(void**)&qgnutls_certificate_set_x509_key_mem, "gnutls_certificate_set_x509_key_mem"}, {(void**)&qgnutls_certificate_set_x509_key_mem, "gnutls_certificate_set_x509_key_mem"},
{(void**)&qgnutls_certificate_get_x509_key, "gnutls_certificate_get_x509_key"},
{(void**)&qgnutls_certificate_free_credentials, "gnutls_certificate_free_credentials"},
{(void**)&qgnutls_pubkey_init, "gnutls_pubkey_init"},
{(void**)&qgnutls_pubkey_import_x509, "gnutls_pubkey_import_x509"},
{(void**)&qgnutls_privkey_sign_hash, "gnutls_privkey_sign_hash"},
{(void**)&qgnutls_pubkey_verify_hash2, "gnutls_pubkey_verify_hash2"},
{(void**)&qgnutls_x509_crt_import, "gnutls_x509_crt_import"},
{NULL, NULL} {NULL, NULL}
}; };
@ -835,17 +848,68 @@ static gnutls_certificate_credentials_t xcred[2];
static gnutls_datum_t cookie_key; static gnutls_datum_t cookie_key;
#endif #endif
vfsfile_t *SSL_OpenPrivKey(char *nativename, size_t nativesize)
{
#define privname "privkey.pem"
vfsfile_t *privf;
const char *mode = nativename?"wb":"rb";
int i = COM_CheckParm("-privkey");
if (i++)
{
if (nativename)
Q_strncpyz(nativename, com_argv[i], nativesize);
privf = FS_OpenVFS(com_argv[i], mode, FS_SYSTEM);
}
else
{
if (nativename)
if (!FS_NativePath(privname, FS_ROOT, nativename, nativesize))
return NULL;
privf = FS_OpenVFS(privname, mode, FS_ROOT);
}
return privf;
#undef privname
}
vfsfile_t *SSL_OpenPubKey(char *nativename, size_t nativesize)
{
#define pubname "cert.pem"
vfsfile_t *pubf;
const char *mode = nativename?"wb":"rb";
int i = COM_CheckParm("-pubkey");
if (i++)
{
if (nativename)
Q_strncpyz(nativename, com_argv[i], nativesize);
pubf = FS_OpenVFS(com_argv[i], mode, FS_SYSTEM);
}
else
{
if (nativename)
if (!FS_NativePath(pubname, FS_ROOT, nativename, nativesize))
return NULL;
pubf = FS_OpenVFS(pubname, mode, FS_ROOT);
}
return pubf;
#undef pubname
}
static qboolean SSL_LoadPrivateCert(gnutls_certificate_credentials_t cred) static qboolean SSL_LoadPrivateCert(gnutls_certificate_credentials_t cred)
{ {
int ret = -1; int ret = -1;
gnutls_datum_t priv, pub; gnutls_datum_t priv, pub;
vfsfile_t *privf = FS_OpenVFS(privname, "rb", FS_ROOT); vfsfile_t *privf = SSL_OpenPrivKey(NULL, 0);
vfsfile_t *pubf = FS_OpenVFS(pubname, "rb", FS_ROOT); vfsfile_t *pubf = SSL_OpenPubKey(NULL, 0);
const char *hostname = NULL;
int i = COM_CheckParm("-certhost");
if (i)
hostname = com_argv[i+1];
memset(&priv, 0, sizeof(priv)); memset(&priv, 0, sizeof(priv));
memset(&pub, 0, sizeof(pub)); memset(&pub, 0, sizeof(pub));
if (!privf || !pubf) if ((!privf || !pubf) && hostname)
{ //not found? generate a new one. { //not found? generate a new one.
//FIXME: how to deal with race conditions with multiple servers on the same host? //FIXME: how to deal with race conditions with multiple servers on the same host?
//delay till the first connection? we at least write both files at the sameish time. //delay till the first connection? we at least write both files at the sameish time.
@ -856,7 +920,7 @@ static qboolean SSL_LoadPrivateCert(gnutls_certificate_credentials_t cred)
char serial[64]; char serial[64];
const char *errstr; const char *errstr;
gnutls_pk_algorithm_t privalgo = GNUTLS_PK_RSA; gnutls_pk_algorithm_t privalgo = GNUTLS_PK_RSA;
if (privf)VFS_CLOSE(privf);privf=NULL; if (privf)VFS_CLOSE(privf);privf=NULL;
if (pubf)VFS_CLOSE(pubf);pubf=NULL; if (pubf)VFS_CLOSE(pubf);pubf=NULL;
@ -880,11 +944,16 @@ static qboolean SSL_LoadPrivateCert(gnutls_certificate_credentials_t cred)
qgnutls_x509_crt_set_activation_time(cert, time(NULL)-1); qgnutls_x509_crt_set_activation_time(cert, time(NULL)-1);
qgnutls_x509_crt_set_expiration_time(cert, time(NULL)+(time_t)10*365*24*60*60); qgnutls_x509_crt_set_expiration_time(cert, time(NULL)+(time_t)10*365*24*60*60);
qgnutls_x509_crt_set_serial(cert, serial, strlen(serial)); qgnutls_x509_crt_set_serial(cert, serial, strlen(serial));
if (qgnutls_x509_crt_set_dn(cert, "CN=localhost", &errstr) < 0) if (!hostname)
Con_Printf("gnutls_x509_crt_set_dn failed: %s\n", errstr); /*qgnutls_x509_crt_set_key_usage(cert, GNUTLS_KEY_DIGITAL_SIGNATURE)*/;
if (qgnutls_x509_crt_set_issuer_dn(cert, "CN=localhost", &errstr) < 0) else
Con_Printf("gnutls_x509_crt_set_issuer_dn failed: %s\n", errstr); {
// qgnutls_x509_crt_set_key_usage(cert, GNUTLS_KEY_KEY_ENCIPHERMENT|GNUTLS_KEY_DATA_ENCIPHERMENT|); if (qgnutls_x509_crt_set_dn(cert, va("CN=%s", hostname), &errstr) < 0)
Con_Printf("gnutls_x509_crt_set_dn failed: %s\n", errstr);
if (qgnutls_x509_crt_set_issuer_dn(cert, va("CN=%s", hostname), &errstr) < 0)
Con_Printf("gnutls_x509_crt_set_issuer_dn failed: %s\n", errstr);
// qgnutls_x509_crt_set_key_usage(cert, GNUTLS_KEY_KEY_ENCIPHERMENT|GNUTLS_KEY_DATA_ENCIPHERMENT|);
}
qgnutls_x509_crt_set_key(cert, key); qgnutls_x509_crt_set_key(cert, key);
/*sign it with our private key*/ /*sign it with our private key*/
@ -906,31 +975,29 @@ static qboolean SSL_LoadPrivateCert(gnutls_certificate_credentials_t cred)
if (priv.size && pub.size) if (priv.size && pub.size)
{ {
char fullname[MAX_OSPATH]; char fullname[MAX_OSPATH];
privf = FS_OpenVFS(privname, "wb", FS_ROOT); privf = SSL_OpenPrivKey(fullname, sizeof(fullname));
if (privf) if (privf)
{ {
VFS_WRITE(privf, priv.data, priv.size); VFS_WRITE(privf, priv.data, priv.size);
VFS_CLOSE(privf); VFS_CLOSE(privf);
FS_NativePath(privname, FS_ROOT, fullname, sizeof(fullname));
Con_Printf("Wrote %s\n", fullname); Con_Printf("Wrote %s\n", fullname);
} }
// memset(priv.data, 0, priv.size); // memset(priv.data, 0, priv.size);
(*qgnutls_free)(priv.data); (*qgnutls_free)(priv.data);
memset(&priv, 0, sizeof(priv)); memset(&priv, 0, sizeof(priv));
pubf = FS_OpenVFS(pubname, "wb", FS_ROOT); pubf = SSL_OpenPubKey(fullname, sizeof(fullname));
if (pubf) if (pubf)
{ {
VFS_WRITE(pubf, pub.data, pub.size); VFS_WRITE(pubf, pub.data, pub.size);
VFS_CLOSE(pubf); VFS_CLOSE(pubf);
FS_NativePath(pubname, FS_ROOT, fullname, sizeof(fullname));
Con_Printf("Wrote %s\n", fullname); Con_Printf("Wrote %s\n", fullname);
} }
(*qgnutls_free)(pub.data); (*qgnutls_free)(pub.data);
memset(&pub, 0, sizeof(pub)); memset(&pub, 0, sizeof(pub));
privf = FS_OpenVFS(privname, "rb", FS_ROOT); privf = SSL_OpenPrivKey(NULL, 0);
pubf = FS_OpenVFS(pubname, "rb", FS_ROOT); pubf = SSL_OpenPubKey(NULL, 0);
Con_Printf("Certificate generated\n"); Con_Printf("Certificate generated\n");
} }
@ -961,7 +1028,7 @@ static qboolean SSL_LoadPrivateCert(gnutls_certificate_credentials_t cred)
Con_Printf("gnutls_certificate_set_x509_key_mem failed: %i\n", ret); Con_Printf("gnutls_certificate_set_x509_key_mem failed: %i\n", ret);
} }
else else
Con_Printf("Unable to read/generate cert\n"); Con_Printf("Unable to read/generate cert ('-certhost HOSTNAME' commandline arguments to autogenerate one)\n");
memset(priv.data, 0, priv.size);//just in case. FIXME: we didn't scrub the filesystem code. libc has its own caches etc. lets hope that noone comes up with some way to scrape memory remotely (although if they can inject code then we've lost either way so w/e) memset(priv.data, 0, priv.size);//just in case. FIXME: we didn't scrub the filesystem code. libc has its own caches etc. lets hope that noone comes up with some way to scrape memory remotely (although if they can inject code then we've lost either way so w/e)
if (priv.data) if (priv.data)
@ -1167,7 +1234,84 @@ int GNUTLS_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize)
} }
} }
//generates a signed blob
int GNUTLS_GenerateSignature(qbyte *hashdata, size_t hashsize, qbyte *signdata, size_t signsizemax)
{
gnutls_datum_t hash = {hashdata, hashsize};
gnutls_datum_t sign = {NULL, 0};
gnutls_certificate_credentials_t cred;
if (Init_GNUTLS())
{
qgnutls_certificate_allocate_credentials (&cred);
if (SSL_LoadPrivateCert(cred))
{
gnutls_x509_privkey_t xkey;
gnutls_privkey_t privkey;
qgnutls_privkey_init(&privkey);
qgnutls_certificate_get_x509_key(cred, 0, &xkey);
qgnutls_privkey_import_x509(privkey, xkey, 0);
qgnutls_privkey_sign_hash(privkey, GNUTLS_DIG_SHA512, 0, &hash, &sign);
qgnutls_privkey_deinit(privkey);
}
else
sign.size = 0;
qgnutls_certificate_free_credentials(cred);
}
else
Con_Printf("Unable to init gnutls\n");
memcpy(signdata, sign.data, sign.size);
return sign.size;
}
//windows equivelent https://docs.microsoft.com/en-us/windows/win32/seccrypto/example-c-program-signing-a-hash-and-verifying-the-hash-signature
enum hashvalidation_e GNUTLS_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize)
{
gnutls_datum_t hash = {hashdata, hashsize};
gnutls_datum_t sign = {signdata, signsize};
int r;
gnutls_datum_t rawcert;
#if 1
size_t sz;
gnutls_pubkey_t pubkey;
gnutls_x509_crt_t cert;
rawcert.data = Auth_GetKnownCertificate(authority, &sz);
if (!rawcert.data)
return VH_AUTHORITY_UNKNOWN;
if (!Init_GNUTLS())
return VH_UNSUPPORTED;
rawcert.size = sz;
qgnutls_pubkey_init(&pubkey);
qgnutls_x509_crt_init(&cert);
qgnutls_x509_crt_import(cert, &rawcert, GNUTLS_X509_FMT_PEM);
qgnutls_pubkey_import_x509(pubkey, cert, 0);
#else
qgnutls_pubkey_import(pubkey, rawcert, GNUTLS_X509_FMT_PEM);
#endif
r = qgnutls_pubkey_verify_hash2(pubkey, GNUTLS_SIGN_RSA_SHA512, 0, &hash, &sign);
if (r < 0)
{
if (r == GNUTLS_E_PK_SIG_VERIFY_FAILED)
{
Con_Printf("GNUTLS_VerifyHash: GNUTLS_E_PK_SIG_VERIFY_FAILED!\n");
return VH_INCORRECT;
}
else if (r == GNUTLS_E_INSUFFICIENT_SECURITY)
{
Con_Printf("GNUTLS_VerifyHash: GNUTLS_E_INSUFFICIENT_SECURITY\n");
return VH_AUTHORITY_UNKNOWN; //should probably be incorrect or something, but oh well
}
return VH_INCORRECT;
}
else
return VH_CORRECT;
}
#ifdef HAVE_DTLS #ifdef HAVE_DTLS

View file

@ -1290,4 +1290,78 @@ const dtlsfuncs_t *SSPI_DTLS_InitClient(void)
} }
#endif #endif
#include <ntstatus.h>
enum hashvalidation_e SSPI_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize)
{
NTSTATUS status;
BCRYPT_KEY_HANDLE pubkey;
size_t sz;
const char *pem = Auth_GetKnownCertificate(authority, &sz);
const char *pemend;
qbyte *der;
size_t dersize;
static const void *(WINAPI *pCertCreateContext) (DWORD dwContextType, DWORD dwEncodingType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCERT_CREATE_CONTEXT_PARA pCreatePara);
static WINBOOL (WINAPI *pCryptImportPublicKeyInfoEx2) (DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, DWORD dwFlags, void *pvAuxInfo, BCRYPT_KEY_HANDLE *phKey);
static WINBOOL (WINAPI *pCertFreeCertificateContext) (PCCERT_CONTEXT pCertContext);
static dllhandle_t *crypt32;
static dllfunction_t crypt32funcs[] = {
{(void**)&pCertCreateContext, "CertCreateContext"},
{(void**)&pCryptImportPublicKeyInfoEx2, "CryptImportPublicKeyInfoEx2"}, //WARNING: fails on wine.
{(void**)&pCertFreeCertificateContext, "CertFreeCertificateContext"},
{NULL,NULL}
};
static NTSTATUS (WINAPI *pBCryptVerifySignature) (BCRYPT_KEY_HANDLE hKey, VOID *pPaddingInfo, PUCHAR pbHash, ULONG cbHash, PUCHAR pbSignature, ULONG cbSignature, ULONG dwFlags);
static NTSTATUS (WINAPI *pBCryptDestroyKey) (BCRYPT_KEY_HANDLE hKey);
static dllhandle_t *bcrypt;
static dllfunction_t bcryptfuncs[] = {
{(void**)&pBCryptVerifySignature, "BCryptVerifySignature"},
{(void**)&pBCryptDestroyKey, "BCryptDestroyKey"},
{NULL,NULL}
};
if (!crypt32)
crypt32 = Sys_LoadLibrary("crypt32.dll", crypt32funcs);
if (!bcrypt)
bcrypt = Sys_LoadLibrary("bcrypt.dll", bcryptfuncs);
if (!crypt32 || !bcrypt)
{
Con_Printf("Unable to obtain required crypto functions\n");
return VH_UNSUPPORTED;
}
if (!pem)
return VH_AUTHORITY_UNKNOWN; //no public cert/key for authority.
pem = strstr(pem, "-----BEGIN CERTIFICATE-----");
if (!pem)
return VH_UNSUPPORTED; //not a pem
pem += strlen("-----BEGIN CERTIFICATE-----");
pemend = strstr(pem, "-----END CERTIFICATE-----");
if (!pemend)
return VH_UNSUPPORTED;
dersize = Base64_DecodeBlock(pem, pemend, NULL, 0); //guess
der = alloca(dersize);
dersize = Base64_DecodeBlock(pem, pemend, der, dersize);
//okay, now its in binary der format.
//make sense of the cert and pull out its public key...
{
const CERT_CONTEXT* cert = pCertCreateContext(CERT_STORE_CERTIFICATE_CONTEXT, X509_ASN_ENCODING, der, dersize, 0, NULL);
if (!pCryptImportPublicKeyInfoEx2(X509_ASN_ENCODING, &cert->pCertInfo->SubjectPublicKeyInfo, 0, NULL, &pubkey))
return VH_UNSUPPORTED;
pCertFreeCertificateContext(cert);
}
//yay, now we can do what we actually wanted in the first place.
status = pBCryptVerifySignature(pubkey, NULL, hashdata, hashsize, signdata, signsize, 0);
pBCryptDestroyKey(pubkey);
if (status == STATUS_SUCCESS)
return VH_CORRECT; //its okay
else if (status == STATUS_INVALID_SIGNATURE)
return VH_INCORRECT; //its bad
return VH_UNSUPPORTED; //some weird transient error...?
}
#endif #endif

View file

@ -2178,6 +2178,49 @@ qboolean NET_IsLoopBackAddress (netadr_t *adr)
#ifdef HAVE_SSL #ifdef HAVE_SSL
void *Auth_GetKnownCertificate(const char *certname, size_t *size)
{ //our 'code signing' certs
//we only allow packages to be installed into the root dir (or with dll/so/exe extensions) when their signature is signed by one of these certificates
static struct
{
const char *name;
qbyte *cert;
} certs[] =
{ //the contents of a -pubcert FILE
{"Spike", "-----BEGIN CERTIFICATE-----\n"
"MIIDnTCCAgUCCjE1ODQ4ODg2OTEwDQYJKoZIhvcNAQELBQAwEDEOMAwGA1UEAxMF\n"
"U3Bpa2UwHhcNMjAwMzIyMTQ1MTMwWhcNMzAwMzIwMTQ1MTMxWjAQMQ4wDAYDVQQD\n"
"EwVTcGlrZTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAN07KHTPc0Pn\n"
"lC8MlQNiI+OEUEJBakTjfNq+IJzJ6oTWXxfQbHrN+UpKXwxploDbeyxTE1Fniisi\n"
"nLWhOkW/XQqyXLXAv/3lxiSwe4QcVMOhQlw5U05VrdB7xHvFMShLsyc12sNvBiIa\n"
"Vw05wFJgIXYTd9nJfm9x3kpxRoTJBvdDbYl8OagT6SxzJfHkdmfI2TYVYxGUH9nX\n"
"R9zvwXTIXvV47cko2ON8scH9QQ6KgwMfcwyIBL74Btvl4ye+TrL2srj38FBxyyPG\n"
"SSdKPk4LN2zsfNsJm31hzWrdLEkl3CTOX5gHHSweOKpuPwmX/GPd1xo0nIMwDou4\n"
"BsMMBAhK/JSyLpUUzk5gbRmy4PwFccktHdFW6LF8ZvPY7e7LEiD5KOWZ7a7c1WR/\n"
"4oJrjo0t+7OugVADolxzLXFrq9ACBGrD8r6QlsGC8O7WqpKGQCT+4q3tUup9tPkh\n"
"3dhjC0jEkKljS+39uukbisV702bHwoEZPzjMpz4O9bHf6JbIJLlQzQIDAQABMA0G\n"
"CSqGSIb3DQEBCwUAA4IBgQC5rj7R7a9LLnqgiXMUITGnygK1lp0EV2BdnIrg/MHr\n"
"y+Gk9BA+XgFSI4W9odiG/hJnA7aQ0S2kk1GNYQ+NNzU2bQIMkaobaZApV9ojD4lL\n"
"s33Qbgt/Ocpadtpj8EiMInjLkn1B+wnqcX3S76Zcrf8RT4WP2A4klxcN3zBNBiBL\n"
"DAJ3SrH8hZ9wmruwAY5tMZhQzDHkeK8uaDb7nE0HA5GXeT4QYA/L7Ys2nGYgxj1O\n"
"L5YlGddBcX3O6XyJpSeCO2Z2kwl4qg8oiM+Y546lILotuL5qD/+FTDeX3dGd8nyD\n"
"e1g/7xd0V4IyKUjii8Vu2V1F7t0xVTPWEe13TqU/JTfKX4zvQnMF7zxgGFIwabHX\n"
"lzk2olte4rPp+iQzPmnynLiUrdkxGXLnE0V545VO+iGO8+bwclbJ+7SG6N5l8xox\n"
"WjGunhXXkEjitAk+ssBjbEh8kIfpFdVA09v60rMdm7BdfO3//QOsjwiwKkBOXcYW\n"
"QGE0Ue4J7anLVAKiQq4n1aU=\n"
"-----END CERTIFICATE-----\n"},
};
size_t i;
for (i = 0; i < countof(certs); i++)
{
if (!strcmp(certname, certs[i].name))
{
*size = strlen(certs[i].cert);
return certs[i].cert;
}
}
return NULL;
}
void *TLS_GetKnownCertificate(const char *certname, size_t *size) void *TLS_GetKnownCertificate(const char *certname, size_t *size)
{ {
//Note: This is XORed because of shitty scanners flagging binaries through false positive, flagging the sites that they were downloaded from, flagging binaries that contain references to those sites, and flagging any site that contains binaries. //Note: This is XORed because of shitty scanners flagging binaries through false positive, flagging the sites that they were downloaded from, flagging binaries that contain references to those sites, and flagging any site that contains binaries.
@ -4851,7 +4894,7 @@ qboolean FTENET_TCP_ParseHTTPRequest(ftenet_tcp_connection_t *con, ftenet_tcp_st
char *protoname = ""; char *protoname = "";
blurgh = va("%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", arg[WCATTR_WSKEY]); blurgh = va("%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", arg[WCATTR_WSKEY]);
tobase64(acceptkey, sizeof(acceptkey), sha1digest, SHA1(sha1digest, sizeof(sha1digest), blurgh, strlen(blurgh))); tobase64(acceptkey, sizeof(acceptkey), sha1digest, CalcHash(&hash_sha1, sha1digest, sizeof(sha1digest), blurgh, strlen(blurgh)));
if (st->remoteaddr.prot == NP_TLS) if (st->remoteaddr.prot == NP_TLS)
st->remoteaddr.prot = NP_WSS; st->remoteaddr.prot = NP_WSS;
@ -8114,12 +8157,14 @@ qboolean NET_Sleep(float seconds, qboolean stdinissocket)
FD_ZERO(&readfdset); FD_ZERO(&readfdset);
FD_ZERO(&writefdset); FD_ZERO(&writefdset);
#ifndef _WIN32
if (stdinissocket) if (stdinissocket)
{ {
sock = STDIN_FILENO; //stdin tends to be socket/filehandle 0 in unix sock = STDIN_FILENO; //stdin tends to be socket/filehandle 0 in unix
FD_SET(sock, &readfdset); FD_SET(sock, &readfdset);
maxfd = sock; maxfd = sock;
} }
#endif
#ifdef SV_MASTER #ifdef SV_MASTER
{ {
@ -8185,8 +8230,10 @@ qboolean NET_Sleep(float seconds, qboolean stdinissocket)
select(maxfd+1, &readfdset, &writefdset, NULL, &timeout); select(maxfd+1, &readfdset, &writefdset, NULL, &timeout);
} }
#ifndef _WIN32
if (stdinissocket) if (stdinissocket)
return FD_ISSET(STDIN_FILENO, &readfdset); return FD_ISSET(STDIN_FILENO, &readfdset);
#endif
#endif #endif
return true; return true;
} }

View file

@ -337,6 +337,13 @@ typedef struct ftenet_generic_connection_s {
#endif #endif
} ftenet_generic_connection_t; } ftenet_generic_connection_t;
enum hashvalidation_e
{
VH_UNSUPPORTED, //library not loaded (bad but not malicious)
VH_AUTHORITY_UNKNOWN, //don't know who signed it / untrusted (bad but probably not malicious)
VH_INCORRECT, //signature is wrong for that authority (bad, probably maliciously so)
VH_CORRECT //all is well.
};
#ifdef HAVE_DTLS #ifdef HAVE_DTLS
typedef struct dtlsfuncs_s typedef struct dtlsfuncs_s
{ {
@ -355,18 +362,22 @@ const dtlsfuncs_t *DTLS_InitClient(void);
int SSPI_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize); int SSPI_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize);
const dtlsfuncs_t *SSPI_DTLS_InitServer(void); //returns NULL if there's no cert available. const dtlsfuncs_t *SSPI_DTLS_InitServer(void); //returns NULL if there's no cert available.
const dtlsfuncs_t *SSPI_DTLS_InitClient(void); //should always return something, if implemented. const dtlsfuncs_t *SSPI_DTLS_InitClient(void); //should always return something, if implemented.
enum hashvalidation_e SSPI_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize);
#endif #endif
#ifdef HAVE_GNUTLS #ifdef HAVE_GNUTLS
vfsfile_t *GNUTLS_OpenVFS(const char *hostname, vfsfile_t *source, qboolean isserver); vfsfile_t *GNUTLS_OpenVFS(const char *hostname, vfsfile_t *source, qboolean isserver);
int GNUTLS_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize); int GNUTLS_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize);
const dtlsfuncs_t *GNUDTLS_InitServer(void); //returns NULL if there's no cert available. const dtlsfuncs_t *GNUDTLS_InitServer(void); //returns NULL if there's no cert available.
const dtlsfuncs_t *GNUDTLS_InitClient(void); //should always return something, if implemented. const dtlsfuncs_t *GNUDTLS_InitClient(void); //should always return something, if implemented.
enum hashvalidation_e GNUTLS_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize);
int GNUTLS_GenerateSignature(qbyte *hashdata, size_t hashsize, qbyte *signdata, size_t signsizemax);
#endif #endif
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
vfsfile_t *OSSL_OpenVFS(const char *hostname, vfsfile_t *source, qboolean isserver); vfsfile_t *OSSL_OpenVFS(const char *hostname, vfsfile_t *source, qboolean isserver);
int OSSL_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize); int OSSL_GetChannelBinding(vfsfile_t *vf, qbyte *binddata, size_t *bindsize);
const dtlsfuncs_t *OSSL_InitServer(void); //returns NULL if there's no cert available. const dtlsfuncs_t *OSSL_InitServer(void); //returns NULL if there's no cert available.
const dtlsfuncs_t *OSSL_InitClient(void); //should always return something, if implemented. const dtlsfuncs_t *OSSL_InitClient(void); //should always return something, if implemented.
enum hashvalidation_e OSSL_VerifyHash(qbyte *hashdata, size_t hashsize, const char *authority, qbyte *signdata, size_t signsize);
#endif #endif
@ -436,6 +447,7 @@ qboolean FTENET_AddToCollection(struct ftenet_connections_s *col, const char *na
int NET_EnumerateAddresses(ftenet_connections_t *collection, struct ftenet_generic_connection_s **con, unsigned int *adrflags, netadr_t *addresses, const char **adrparams, int maxaddresses); int NET_EnumerateAddresses(ftenet_connections_t *collection, struct ftenet_generic_connection_s **con, unsigned int *adrflags, netadr_t *addresses, const char **adrparams, int maxaddresses);
void *TLS_GetKnownCertificate(const char *certname, size_t *size); void *TLS_GetKnownCertificate(const char *certname, size_t *size);
void *Auth_GetKnownCertificate(const char *certname, size_t *size);
vfsfile_t *FS_OpenSSL(const char *hostname, vfsfile_t *source, qboolean server); vfsfile_t *FS_OpenSSL(const char *hostname, vfsfile_t *source, qboolean server);
int TLS_GetChannelBinding(vfsfile_t *stream, qbyte *data, size_t *datasize); //datasize should be preinitialised to the max length allowed. -1 for not implemented. 0 for peer problems. 1 for success int TLS_GetChannelBinding(vfsfile_t *stream, qbyte *data, size_t *datasize); //datasize should be preinitialised to the max length allowed. -1 for not implemented. 0 for peer problems. 1 for success
#ifdef HAVE_PACKET #ifdef HAVE_PACKET

View file

@ -4649,15 +4649,15 @@ static void QCBUILTIN PF_digest_internal (pubprogfuncs_t *prinst, struct globalv
} }
//md5? //md5?
else if (!strcmp(hashtype, "SHA1")) else if (!strcmp(hashtype, "SHA1"))
{ digestsize = CalcHash(&hash_sha1, digest, sizeof(digest), str, len);
digestsize = SHA1(digest, sizeof(digest), str, len); else if (!strcmp(hashtype, "SHA224"))
} digestsize = CalcHash(&hash_sha224, digest, sizeof(digest), str, len);
// else if (!strcmp(hashtype, "SHA256")) else if (!strcmp(hashtype, "SHA256"))
// { digestsize = CalcHash(&hash_sha256, digest, sizeof(digest), str, len);
// digestsize = SHA2(digest, sizeof(digest), str, len); else if (!strcmp(hashtype, "SHA384"))
// } digestsize = CalcHash(&hash_sha384, digest, sizeof(digest), str, len);
//sha384 else if (!strcmp(hashtype, "SHA512"))
//sha512 digestsize = CalcHash(&hash_sha512, digest, sizeof(digest), str, len);
else if (!strcmp(hashtype, "CRC16")) else if (!strcmp(hashtype, "CRC16"))
{ {
digestsize = 2; digestsize = 2;

View file

@ -1727,7 +1727,7 @@ Rendering functions (Client only)
extern int r_dlightframecount; extern int r_dlightframecount;
//goes through the nodes marking the surfaces near the dynamic light as lit. //goes through the nodes marking the surfaces near the dynamic light as lit.
void Q1BSP_MarkLights (dlight_t *light, int bit, mnode_t *node) void Q1BSP_MarkLights (dlight_t *light, dlightbitmask_t bit, mnode_t *node)
{ {
mplane_t *splitplane; mplane_t *splitplane;
float dist; float dist;

View file

@ -14,11 +14,20 @@ A million repetitions of "a"
This file came to FTE via EzQuake. This file came to FTE via EzQuake.
*/ */
/* #define SHA1HANDSOFF * Copies data before messing with it. */
#define SHA1HANDSOFF
#include "quakedef.h" #include "quakedef.h"
#include <string.h> #include <string.h>
/* #define SHA1HANDSOFF * Copies data before messing with it. */
#define SHA1HANDSOFF
typedef struct
{
unsigned int state[5];
size_t count[2];
unsigned char buffer[64];
} SHA1_CTX;
#define SHA1_DIGEST_SIZE 20
#define BigLong(l) (((unsigned char*)&l)[0]<<24) | (((unsigned char*)&l)[1]<<16) | (((unsigned char*)&l)[2]<<8) | (((unsigned char*)&l)[3]<<0) #define BigLong(l) (((unsigned char*)&l)[0]<<24) | (((unsigned char*)&l)[1]<<16) | (((unsigned char*)&l)[2]<<8) | (((unsigned char*)&l)[3]<<0)
@ -36,23 +45,9 @@ This file came to FTE via EzQuake.
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
typedef struct
{
unsigned int state[5];
size_t count[2];
unsigned char buffer[64];
} SHA1_CTX;
#define DIGEST_SIZE 20
void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]);
void SHA1Init(SHA1_CTX* context);
void SHA1Update(SHA1_CTX* context, const unsigned char* data, size_t len);
void SHA1Final(unsigned char digest[DIGEST_SIZE], SHA1_CTX* context);
/* Hash a single 512-bit block. This is the core of the algorithm. */ /* Hash a single 512-bit block. This is the core of the algorithm. */
void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]) static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64])
{ {
unsigned int a, b, c, d, e; unsigned int a, b, c, d, e;
typedef union typedef union
@ -108,8 +103,9 @@ void SHA1Transform(unsigned int state[5], const unsigned char buffer[64])
/* SHA1Init - Initialize new context */ /* SHA1Init - Initialize new context */
void SHA1Init(SHA1_CTX* context) static void SHA1Init(void *ctx)
{ {
SHA1_CTX *context = ctx;
/* SHA1 initialization constants */ /* SHA1 initialization constants */
context->state[0] = 0x67452301; context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89; context->state[1] = 0xEFCDAB89;
@ -122,8 +118,9 @@ void SHA1Init(SHA1_CTX* context)
/* Run your data through this. */ /* Run your data through this. */
void SHA1Update(SHA1_CTX* context, const unsigned char* data, size_t len) static void SHA1Update(void *ctx, const void* data, size_t len)
{ {
SHA1_CTX *context = ctx;
size_t i, j; size_t i, j;
j = (context->count[0] >> 3) & 63; j = (context->count[0] >> 3) & 63;
@ -135,20 +132,21 @@ void SHA1Update(SHA1_CTX* context, const unsigned char* data, size_t len)
SHA1Transform(context->state, context->buffer); SHA1Transform(context->state, context->buffer);
for ( ; i + 63 < len; i += 64) for ( ; i + 63 < len; i += 64)
{ {
SHA1Transform(context->state, &data[i]); SHA1Transform(context->state, (const qbyte*)data + i);
} }
j = 0; j = 0;
} }
else else
i = 0; i = 0;
memcpy(&context->buffer[j], &data[i], len - i); memcpy(&context->buffer[j], (const qbyte*)data + i, len - i);
} }
/* Add padding and return the message digest. */ /* Add padding and return the message digest. */
void SHA1Final(unsigned char digest[DIGEST_SIZE], SHA1_CTX* context) static void SHA1Final(unsigned char digest[SHA1_DIGEST_SIZE], void *ctx)
{ {
SHA1_CTX *context = ctx;
unsigned int i, j; unsigned int i, j;
unsigned char finalcount[8]; unsigned char finalcount[8];
@ -162,7 +160,7 @@ void SHA1Final(unsigned char digest[DIGEST_SIZE], SHA1_CTX* context)
SHA1Update(context, (unsigned char *)"\0", 1); SHA1Update(context, (unsigned char *)"\0", 1);
} }
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < DIGEST_SIZE; i++) for (i = 0; i < SHA1_DIGEST_SIZE; i++)
{ {
digest[i] = (unsigned char) digest[i] = (unsigned char)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
@ -178,33 +176,26 @@ memset(&finalcount, 0, 8);
#endif #endif
} }
hashfunc_t hash_sha1 =
size_t SHA1(unsigned char *digest, size_t maxdigestsize, const unsigned char *string, size_t stringlen)
{ {
SHA1_CTX context; SHA1_DIGEST_SIZE,
if (maxdigestsize < DIGEST_SIZE) sizeof(SHA1_CTX),
return 0; SHA1Init,
SHA1Update,
SHA1Final,
};
SHA1Init(&context);
SHA1Update(&context, (unsigned char*) string, stringlen);
SHA1Final(digest, &context);
return DIGEST_SIZE;
}
size_t SHA1_m(unsigned char *digest, size_t maxdigestsize, size_t numstrings, const unsigned char **strings, size_t *stringlens) size_t CalcHash(hashfunc_t *func, unsigned char *digest, size_t maxdigestsize, const unsigned char *string, size_t stringlen)
{ {
size_t i; void *ctx = alloca(func->contextsize);
SHA1_CTX context; if (maxdigestsize < func->digestsize)
if (maxdigestsize < DIGEST_SIZE) return 0; //panic
return 0; func->init(ctx);
func->process(ctx, string, stringlen);
SHA1Init(&context); func->terminate(digest, ctx);
for (i = 0; i < numstrings; i++) return func->digestsize;
SHA1Update(&context, (unsigned char*) strings[i], stringlens[i]);
SHA1Final(digest, &context);
return DIGEST_SIZE;
} }
/* hmac-sha1.c -- hashed message authentication codes /* hmac-sha1.c -- hashed message authentication codes
@ -245,18 +236,23 @@ size_t HMAC(hashfunc_t *hashfunc, unsigned char *digest, size_t maxdigestsize,
const unsigned char *data, size_t datalen, const unsigned char *data, size_t datalen,
const unsigned char *key, size_t keylen) const unsigned char *key, size_t keylen)
{ {
#define HMAC_DIGEST_MAXSIZE 20 #define HMAC_DIGEST_MAXSIZE 64
char optkeybuf[HMAC_DIGEST_MAXSIZE]; qbyte optkeybuf[HMAC_DIGEST_MAXSIZE];
char innerhash[HMAC_DIGEST_MAXSIZE]; qbyte innerhash[HMAC_DIGEST_MAXSIZE];
char block[64]; qbyte block[64];
size_t innerhashsize;
if (hashfunc->digestsize > HMAC_DIGEST_MAXSIZE || hashfunc->digestsize > maxdigestsize)
return 0;
/* Reduce the key's size, so that it is never larger than a block. */ /* Reduce the key's size, so that it is never larger than a block. */
if (keylen > sizeof(block)) if (keylen > sizeof(block))
{ {
keylen = hashfunc(optkeybuf, sizeof(optkeybuf), 1, &key, &keylen); qbyte *ctx = alloca(hashfunc->contextsize);
hashfunc->init(ctx);
hashfunc->process(ctx, key, keylen);
hashfunc->terminate(optkeybuf, ctx);
key=optkeybuf; key=optkeybuf;
} }
@ -266,9 +262,11 @@ size_t HMAC(hashfunc_t *hashfunc, unsigned char *digest, size_t maxdigestsize,
memxor (block, key, keylen); memxor (block, key, keylen);
{ {
const unsigned char *strings_i[2] = {block, data}; qbyte *ctx = alloca(hashfunc->contextsize);
size_t stringlens_i[2] = {sizeof(block), datalen}; hashfunc->init(ctx);
innerhashsize = hashfunc(innerhash, sizeof(innerhash), 2, strings_i, stringlens_i); hashfunc->process(ctx, block, sizeof(block));
hashfunc->process(ctx, data, datalen);
hashfunc->terminate(innerhash, ctx);
} }
/* Compute result from KEY and INNERHASH. */ /* Compute result from KEY and INNERHASH. */
@ -277,8 +275,11 @@ size_t HMAC(hashfunc_t *hashfunc, unsigned char *digest, size_t maxdigestsize,
memxor (block, key, keylen); memxor (block, key, keylen);
{ {
const unsigned char *strings_o[2] = {block, innerhash}; qbyte *ctx = alloca(hashfunc->contextsize);
size_t stringlens_o[2] = {sizeof(block), innerhashsize}; hashfunc->init(ctx);
return hashfunc(digest, maxdigestsize, 2, strings_o, stringlens_o); hashfunc->process(ctx, block, sizeof(block));
hashfunc->process(ctx, innerhash, hashfunc->digestsize);
hashfunc->terminate(digest, ctx);
return hashfunc->digestsize;
} }
} }

563
engine/common/sha2.c Normal file
View file

@ -0,0 +1,563 @@
/* sha512.c - SHA384 and SHA512 hash functions
* Copyright (C) 2003, 2008, 2009 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser general Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* Test vectors from FIPS-180-2:
*
* "abc"
* 384:
* CB00753F 45A35E8B B5A03D69 9AC65007 272C32AB 0EDED163
* 1A8B605A 43FF5BED 8086072B A1E7CC23 58BAECA1 34C825A7
* 512:
* DDAF35A1 93617ABA CC417349 AE204131 12E6FA4E 89A97EA2 0A9EEEE6 4B55D39A
* 2192992A 274FC1A8 36BA3C23 A3FEEBBD 454D4423 643CE80E 2A9AC94F A54CA49F
*
* "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
* 384:
* 09330C33 F71147E8 3D192FC7 82CD1B47 53111B17 3B3B05D2
* 2FA08086 E3B0F712 FCC7C71A 557E2DB9 66C3E9FA 91746039
* 512:
* 8E959B75 DAE313DA 8CF4F728 14FC143F 8F7779C6 EB9F7FA1 7299AEAD B6889018
* 501D289E 4900F7E4 331B99DE C4B5433A C7D329EE B6DD2654 5E96E55B 874BE909
*
* "a" x 1000000
* 384:
* 9D0E1809 716474CB 086E834E 310A4A1C ED149E9C 00F24852
* 7972CEC5 704C2A5B 07B8B3DC 38ECC4EB AE97DDD8 7F3D8985
* 512:
* E718483D 0CE76964 4E2E42C7 BC15B463 8E1F98B1 3B204428 5632A803 AFA973EB
* DE0FF244 877EA60A 4CB0432C E577C31B EB009C5C 2C49AA2E 4EADB217 AD8CC09B
*/
#include "quakedef.h"
#ifndef SHA2
#define SHA2 256
#include "sha2.c"
#undef SHA2
#define SHA2 512
#endif
#undef U64_C
#undef U64_C_LOW
#undef u64
#undef ROUNDS
#undef SHA2_CONTEXT
#undef sha2trunc_init
#undef sha2_init
#if SHA2==256
#define U64_C(n) (n##ull>>32)
#define U64_C_LOW(n) (u64)U64_C(n)
#define u64 quint32_t
#define ROUNDS 64
#define SHA2_CONTEXT SHA256_CONTEXT
#define sha2trunc_init sha224_init
#define sha2_init sha256_init
#else
#define U64_C(n) n##ull
#define U64_C_LOW(n) n##ull
#define u64 quint64_t
#define ROUNDS 80
#define SHA2_CONTEXT SHA512_CONTEXT
#define ROTR ROTR64
#define Ch Ch64
#define Maj Maj64
#define Sum0 Sum0_64
#define Sum1 Sum1_64
#define transform transform_64
#define sha2trunc_init sha384_init
#define sha2_init sha512_init
#define sha2_write sha512_write
#define sha2_final sha512_final
#endif
#define BLOCKBYTES (16*sizeof(u64))
#define byte qbyte
typedef struct
{
u64 h0, h1, h2, h3, h4, h5, h6, h7;
u64 nblocks;
byte buf[BLOCKBYTES];
int count;
} SHA2_CONTEXT;
static void
sha2_init (void *context)
{
SHA2_CONTEXT *hd = context;
hd->h0 = U64_C(0x6a09e667f3bcc908);
hd->h1 = U64_C(0xbb67ae8584caa73b);
hd->h2 = U64_C(0x3c6ef372fe94f82b);
hd->h3 = U64_C(0xa54ff53a5f1d36f1);
hd->h4 = U64_C(0x510e527fade682d1);
hd->h5 = U64_C(0x9b05688c2b3e6c1f);
hd->h6 = U64_C(0x1f83d9abfb41bd6b);
hd->h7 = U64_C(0x5be0cd19137e2179);
hd->nblocks = 0;
hd->count = 0;
}
static void sha2trunc_init (void *context)
{
SHA2_CONTEXT *hd = context;
//sha224 uses only the low parts.
hd->h0 = U64_C_LOW(0xcbbb9d5dc1059ed8);
hd->h1 = U64_C_LOW(0x629a292a367cd507);
hd->h2 = U64_C_LOW(0x9159015a3070dd17);
hd->h3 = U64_C_LOW(0x152fecd8f70e5939);
hd->h4 = U64_C_LOW(0x67332667ffc00b31);
hd->h5 = U64_C_LOW(0x8eb44a8768581511);
hd->h6 = U64_C_LOW(0xdb0c2e0d64f98fa7);
hd->h7 = U64_C_LOW(0x47b5481dbefa4fa4);
hd->nblocks = 0;
hd->count = 0;
}
static inline u64
ROTR (u64 x, u64 n)
{
return ((x >> n) | (x << (64 - n)));
}
static inline u64
Ch (u64 x, u64 y, u64 z)
{
return ((x & y) ^ ( ~x & z));
}
static inline u64
Maj (u64 x, u64 y, u64 z)
{
return ((x & y) ^ (x & z) ^ (y & z));
}
#undef S0
#undef S1
#if SHA2==256
#define S0(x) (ROTR((x),7) ^ ROTR((x),18) ^ ((x)>>3))
#define S1(x) (ROTR((x),17) ^ ROTR((x),19) ^ ((x)>>10))
static inline u64
Sum0 (u64 x)
{
return (ROTR (x, 2) ^ ROTR (x, 13) ^ ROTR (x, 22));
}
static inline u64
Sum1 (u64 x)
{
return (ROTR (x, 6) ^ ROTR (x, 11) ^ ROTR (x, 25));
}
#else
#define S0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7))
#define S1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6))
static inline u64
Sum0 (u64 x)
{
return (ROTR (x, 28) ^ ROTR (x, 34) ^ ROTR (x, 39));
}
static inline u64
Sum1 (u64 x)
{
return (ROTR (x, 14) ^ ROTR (x, 18) ^ ROTR (x, 41));
}
#endif
/****************
* Transform the message W which consists of 16 64-bit-words
*/
static void
transform (SHA2_CONTEXT *hd, const unsigned char *data)
{
u64 a, b, c, d, e, f, g, h;
u64 w[ROUNDS];
int t;
static const u64 k[] =
{
U64_C(0x428a2f98d728ae22), U64_C(0x7137449123ef65cd),
U64_C(0xb5c0fbcfec4d3b2f), U64_C(0xe9b5dba58189dbbc),
U64_C(0x3956c25bf348b538), U64_C(0x59f111f1b605d019),
U64_C(0x923f82a4af194f9b), U64_C(0xab1c5ed5da6d8118),
U64_C(0xd807aa98a3030242), U64_C(0x12835b0145706fbe),
U64_C(0x243185be4ee4b28c), U64_C(0x550c7dc3d5ffb4e2),
U64_C(0x72be5d74f27b896f), U64_C(0x80deb1fe3b1696b1),
U64_C(0x9bdc06a725c71235), U64_C(0xc19bf174cf692694),
U64_C(0xe49b69c19ef14ad2), U64_C(0xefbe4786384f25e3),
U64_C(0x0fc19dc68b8cd5b5), U64_C(0x240ca1cc77ac9c65),
U64_C(0x2de92c6f592b0275), U64_C(0x4a7484aa6ea6e483),
U64_C(0x5cb0a9dcbd41fbd4), U64_C(0x76f988da831153b5),
U64_C(0x983e5152ee66dfab), U64_C(0xa831c66d2db43210),
U64_C(0xb00327c898fb213f), U64_C(0xbf597fc7beef0ee4),
U64_C(0xc6e00bf33da88fc2), U64_C(0xd5a79147930aa725),
U64_C(0x06ca6351e003826f), U64_C(0x142929670a0e6e70),
U64_C(0x27b70a8546d22ffc), U64_C(0x2e1b21385c26c926),
U64_C(0x4d2c6dfc5ac42aed), U64_C(0x53380d139d95b3df),
U64_C(0x650a73548baf63de), U64_C(0x766a0abb3c77b2a8),
U64_C(0x81c2c92e47edaee6), U64_C(0x92722c851482353b),
U64_C(0xa2bfe8a14cf10364), U64_C(0xa81a664bbc423001),
U64_C(0xc24b8b70d0f89791), U64_C(0xc76c51a30654be30),
U64_C(0xd192e819d6ef5218), U64_C(0xd69906245565a910),
U64_C(0xf40e35855771202a), U64_C(0x106aa07032bbd1b8),
U64_C(0x19a4c116b8d2d0c8), U64_C(0x1e376c085141ab53),
U64_C(0x2748774cdf8eeb99), U64_C(0x34b0bcb5e19b48a8),
U64_C(0x391c0cb3c5c95a63), U64_C(0x4ed8aa4ae3418acb),
U64_C(0x5b9cca4f7763e373), U64_C(0x682e6ff3d6b2b8a3),
U64_C(0x748f82ee5defb2fc), U64_C(0x78a5636f43172f60),
U64_C(0x84c87814a1f0ab72), U64_C(0x8cc702081a6439ec),
U64_C(0x90befffa23631e28), U64_C(0xa4506cebde82bde9),
U64_C(0xbef9a3f7b2c67915), U64_C(0xc67178f2e372532b),
U64_C(0xca273eceea26619c), U64_C(0xd186b8c721c0c207),
U64_C(0xeada7dd6cde0eb1e), U64_C(0xf57d4f7fee6ed178),
U64_C(0x06f067aa72176fba), U64_C(0x0a637dc5a2c898a6),
U64_C(0x113f9804bef90dae), U64_C(0x1b710b35131c471b),
U64_C(0x28db77f523047d84), U64_C(0x32caab7b40c72493),
U64_C(0x3c9ebe0a15c9bebc), U64_C(0x431d67c49c100d4c),
U64_C(0x4cc5d4becb3e42b6), U64_C(0x597f299cfc657e2a),
U64_C(0x5fcb6fab3ad6faec), U64_C(0x6c44198c4a475817)
};
/* get values from the chaining vars */
a = hd->h0;
b = hd->h1;
c = hd->h2;
d = hd->h3;
e = hd->h4;
f = hd->h5;
g = hd->h6;
h = hd->h7;
#ifdef WORDS_BIGENDIAN
memcpy (w, data, BLOCKBYTES);
#else
{
int i;
byte *p2;
for (i = 0, p2 = (byte *) w; i < 16; i++, p2 += sizeof(*w))
{
#if SHA2==512
p2[7] = *data++;
p2[6] = *data++;
p2[5] = *data++;
p2[4] = *data++;
#endif
p2[3] = *data++;
p2[2] = *data++;
p2[1] = *data++;
p2[0] = *data++;
}
}
#endif
for (t = 16; t < ROUNDS; t++)
w[t] = S1 (w[t - 2]) + w[t - 7] + S0 (w[t - 15]) + w[t - 16];
for (t = 0; t < ROUNDS; )
{
u64 t1, t2;
/* Performance on a AMD Athlon(tm) Dual Core Processor 4050e
with gcc 4.3.3 using gcry_md_hash_buffer of each 10000 bytes
initialized to 0,1,2,3...255,0,... and 1000 iterations:
Not unrolled with macros: 440ms
Unrolled with macros: 350ms
Unrolled with inline: 330ms
*/
#if 0 /* Not unrolled. */
t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t];
t2 = Sum0 (a) + Maj (a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
t++;
#else /* Unrolled to interweave the chain variables. */
t1 = h + Sum1 (e) + Ch (e, f, g) + k[t] + w[t];
t2 = Sum0 (a) + Maj (a, b, c);
d += t1;
h = t1 + t2;
t1 = g + Sum1 (d) + Ch (d, e, f) + k[t+1] + w[t+1];
t2 = Sum0 (h) + Maj (h, a, b);
c += t1;
g = t1 + t2;
t1 = f + Sum1 (c) + Ch (c, d, e) + k[t+2] + w[t+2];
t2 = Sum0 (g) + Maj (g, h, a);
b += t1;
f = t1 + t2;
t1 = e + Sum1 (b) + Ch (b, c, d) + k[t+3] + w[t+3];
t2 = Sum0 (f) + Maj (f, g, h);
a += t1;
e = t1 + t2;
t1 = d + Sum1 (a) + Ch (a, b, c) + k[t+4] + w[t+4];
t2 = Sum0 (e) + Maj (e, f, g);
h += t1;
d = t1 + t2;
t1 = c + Sum1 (h) + Ch (h, a, b) + k[t+5] + w[t+5];
t2 = Sum0 (d) + Maj (d, e, f);
g += t1;
c = t1 + t2;
t1 = b + Sum1 (g) + Ch (g, h, a) + k[t+6] + w[t+6];
t2 = Sum0 (c) + Maj (c, d, e);
f += t1;
b = t1 + t2;
t1 = a + Sum1 (f) + Ch (f, g, h) + k[t+7] + w[t+7];
t2 = Sum0 (b) + Maj (b, c, d);
e += t1;
a = t1 + t2;
t += 8;
#endif
}
/* Update chaining vars. */
hd->h0 += a;
hd->h1 += b;
hd->h2 += c;
hd->h3 += d;
hd->h4 += e;
hd->h5 += f;
hd->h6 += g;
hd->h7 += h;
}
/* Update the message digest with the contents
* of INBUF with length INLEN.
*/
static void
sha2_write (void *context, const void *inbuf_arg, size_t inlen)
{
const unsigned char *inbuf = inbuf_arg;
SHA2_CONTEXT *hd = context;
if (hd->count == BLOCKBYTES)
{ /* flush the buffer */
transform (hd, hd->buf);
hd->count = 0;
hd->nblocks++;
}
if (!inbuf)
return;
if (hd->count)
{
for (; inlen && hd->count < BLOCKBYTES; inlen--)
hd->buf[hd->count++] = *inbuf++;
sha2_write (context, NULL, 0);
if (!inlen)
return;
}
while (inlen >= BLOCKBYTES)
{
transform (hd, inbuf);
hd->count = 0;
hd->nblocks++;
inlen -= BLOCKBYTES;
inbuf += BLOCKBYTES;
}
for (; inlen && hd->count < BLOCKBYTES; inlen--)
hd->buf[hd->count++] = *inbuf++;
}
/* The routine final terminates the computation and
* returns the digest.
* The handle is prepared for a new cycle, but adding bytes to the
* handle will the destroy the returned buffer.
* Returns: 64 bytes representing the digest. When used for sha384,
* we take the leftmost 48 of those bytes.
*/
static void
sha2_final (void *context)
{
SHA2_CONTEXT *hd = context;
u64 t, msb, lsb;
byte *p;
sha2_write (context, NULL, 0); /* flush */ ;
t = hd->nblocks;
/* multiply by 128 to make a byte count */
lsb = t * BLOCKBYTES;
msb = t >> (sizeof(u64)*8-((BLOCKBYTES==128)?7:6));
/* add the count */
t = lsb;
if ((lsb += hd->count) < t)
msb++;
/* multiply by 8 to make a bit count */
t = lsb;
lsb <<= 3;
msb <<= 3;
msb |= t >> (sizeof(u64)*8-3);
if (hd->count < BLOCKBYTES-sizeof(u64)*2)
{ /* enough room */
hd->buf[hd->count++] = 0x80; /* pad */
while (hd->count < BLOCKBYTES-sizeof(u64)*2)
hd->buf[hd->count++] = 0; /* pad */
}
else
{ /* need one extra block */
hd->buf[hd->count++] = 0x80; /* pad character */
while (hd->count < BLOCKBYTES)
hd->buf[hd->count++] = 0;
sha2_write (context, NULL, 0); /* flush */ ;
memset (hd->buf, 0, BLOCKBYTES-sizeof(u64)*2); /* fill next block with zeroes */
}
#if SHA2==256
#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \
*p++ = hd->h##a >> 8; *p++ = hd->h##a; } while (0)
/* append the 128 bit count */
hd->buf[56] = msb >> 24;
hd->buf[57] = msb >> 16;
hd->buf[58] = msb >> 8;
hd->buf[59] = msb;
hd->buf[60] = lsb >> 24;
hd->buf[61] = lsb >> 16;
hd->buf[62] = lsb >> 8;
hd->buf[63] = lsb;
#else
#define X(a) do { *p++ = hd->h##a >> 56; *p++ = hd->h##a >> 48; \
*p++ = hd->h##a >> 40; *p++ = hd->h##a >> 32; \
*p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16; \
*p++ = hd->h##a >> 8; *p++ = hd->h##a; } while (0)
/* append the 128 bit count */
hd->buf[112] = msb >> 56;
hd->buf[113] = msb >> 48;
hd->buf[114] = msb >> 40;
hd->buf[115] = msb >> 32;
hd->buf[116] = msb >> 24;
hd->buf[117] = msb >> 16;
hd->buf[118] = msb >> 8;
hd->buf[119] = msb;
hd->buf[120] = lsb >> 56;
hd->buf[121] = lsb >> 48;
hd->buf[122] = lsb >> 40;
hd->buf[123] = lsb >> 32;
hd->buf[124] = lsb >> 24;
hd->buf[125] = lsb >> 16;
hd->buf[126] = lsb >> 8;
hd->buf[127] = lsb;
#endif
transform (hd, hd->buf);
p = hd->buf;
#ifdef WORDS_BIGENDIAN
#undef X
#define X(a) do { *(u64*)p = hd->h##a ; p += sizeof(u64); } while (0)
#endif
X (0);
X (1);
X (2);
X (3);
X (4);
X (5);
/* Note that these last two chunks are included even for SHA384.
We just ignore them. */
X (6);
X (7);
#undef X
}
#if SHA2==256
static void sha224_finish (qbyte *digest, void *context)
{
SHA2_CONTEXT *hd = (SHA2_CONTEXT *) context;
sha2_final(context);
memcpy(digest, hd->buf, 224/8); //only the first 224 bits of the result...
}
static void sha256_finish (qbyte *digest, void *context)
{
SHA2_CONTEXT *hd = (SHA2_CONTEXT *) context;
sha2_final(context);
memcpy(digest, hd->buf, 256/8);
}
hashfunc_t hash_sha224 =
{
224/8,
sizeof(SHA2_CONTEXT),
sha224_init,
sha2_write,
sha224_finish
};
hashfunc_t hash_sha256 =
{
256/8,
sizeof(SHA2_CONTEXT),
sha256_init,
sha2_write,
sha256_finish
};
#endif
#if SHA2==512
static void sha384_finish (qbyte *digest, void *context)
{
SHA2_CONTEXT *hd = (SHA2_CONTEXT *) context;
sha2_final(context);
memcpy(digest, hd->buf, 384/8);
}
static void sha512_finish (qbyte *digest, void *context)
{
SHA2_CONTEXT *hd = (SHA2_CONTEXT *) context;
sha2_final(context);
memcpy(digest, hd->buf, 512/8);
}
hashfunc_t hash_sha384 =
{
384/8,
sizeof(SHA2_CONTEXT),
sha384_init,
sha2_write,
sha384_finish
};
hashfunc_t hash_sha512 =
{
512/8,
sizeof(SHA2_CONTEXT),
sha512_init,
sha2_write,
sha512_finish
};
#endif

View file

@ -182,17 +182,21 @@ void NPQTV_Sys_MainLoop(void);
#define UPD_STABLE 1 #define UPD_STABLE 1
#define UPD_TESTING 2 #define UPD_TESTING 2
#if defined(WEBCLIENT) && defined(_WIN32) && !defined(SERVERONLY) && !defined(_XBOX) #if defined(WEBCLIENT) && defined(PACKAGEMANAGER)
int StartLocalServer(int close); #if defined(_WIN32) && !defined(SERVERONLY) && !defined(_XBOX)
#define HAVEAUTOUPDATE
#endif
#if defined(__linux__) && !defined(ANDROID)
#define HAVEAUTOUPDATE
#endif
#endif
#define HAVEAUTOUPDATE #ifdef HAVEAUTOUPDATE
qboolean Sys_SetUpdatedBinary(const char *fname); //legacy, so old build can still deal with updates properly qboolean Sys_SetUpdatedBinary(const char *fname); //attempts to overwrite the working binary.
qboolean Sys_EngineMayUpdate(void); //says whether the system code is able to invoke new binaries properly qboolean Sys_EngineMayUpdate(void); //says whether the system code is able/allowed to overwrite itself.
//qboolean Sys_EngineWasUpdated(char *newbinary); //invoke the given system-path binary
#else #else
#define Sys_EngineMayUpdate() false #define Sys_EngineMayUpdate() false
#define Sys_SetUpdatedBinary(n) false #define Sys_SetUpdatedBinary(n) false
//#define Sys_EngineWasUpdated(n) false
#endif #endif
void Sys_Init (void); void Sys_Init (void);

View file

@ -546,3 +546,100 @@ void SSV_CheckFromMaster(void)
} }
} }
#endif #endif
#ifdef HAVEAUTOUPDATE
#include <sys/stat.h>
#include <unistd.h>
qboolean Sys_SetUpdatedBinary(const char *newbinary)
{
char enginebinary[MAX_OSPATH];
char tmpbinary[MAX_OSPATH];
// char enginebinarybackup[MAX_OSPATH+4];
// size_t len;
int i;
struct stat src, dst;
//windows is annoying. we can't delete a file that's in use (no orphaning)
//we can normally rename it to something else before writing a new file with the original name.
//then delete the old file later (sadly only on reboot)
//get the binary name
i = readlink("/proc/self/exe", enginebinary, sizeof(enginebinary)-1);
if (i <= 0)
return false;
enginebinary[i] = 0;
//generate the temp name
/*memcpy(enginebinarybackup, enginebinary, sizeof(enginebinary));
len = strlen(enginebinarybackup);
if (len > 4 && !strcasecmp(enginebinarybackup+len-4, ".bin"))
len -= 4; //swap its extension over, if we can.
strcpy(enginebinarybackup+len, ".bak");*/
//copy over file permissions (don't ignore the user)
if (stat(enginebinary, &dst)<0)
dst.st_mode = 0777;
if (stat(newbinary, &src)<0)
src.st_mode = 0777;
// if (src.st_dev != dst.st_dev)
{ //oops, its on a different filesystem. create a copy
Q_snprintfz(tmpbinary, sizeof(tmpbinary), "%s.new", enginebinary);
if (!FS_Copy(newbinary, tmpbinary, FS_SYSTEM, FS_SYSTEM))
return false;
newbinary = tmpbinary;
}
chmod(newbinary, dst.st_mode|S_IXUSR); //but make sure its executable, just in case...
//overwrite the name we were started through. this is supposed to be atomic.
if (rename(newbinary, enginebinary) < 0)
{
Con_Printf("Failed to overwrite %s with %s\n", enginebinary, newbinary);
return false; //failed
}
return true; //succeeded.
}
qboolean Sys_EngineMayUpdate(void)
{
char enginebinary[MAX_OSPATH];
char *e;
int len;
#define SVNREVISIONSTR STRINGIFY(SVNREVISION)
if (!COM_CheckParm("-allowupdate"))
{
//no revision info in this build, meaning its custom built and thus cannot check against the available updated versions.
if (!strcmp(SVNREVISIONSTR, "-"))
return false;
//svn revision didn't parse as an exact number. this implies it has an 'M' in it to mark it as modified.
//either way, its bad and autoupdates when we don't know what we're updating from is a bad idea.
strtoul(SVNREVISIONSTR, &e, 10);
if (!*SVNREVISIONSTR || *e)
return false;
}
//update blocked via commandline
if (COM_CheckParm("-noupdate") || COM_CheckParm("--noupdate") || COM_CheckParm("-noautoupdate") || COM_CheckParm("--noautoupdate"))
return false;
//check that we can actually do it.
len = readlink("/proc/self/exe", enginebinary, sizeof(enginebinary)-1);
if (len <= 0)
return false;
enginebinary[len] = 0;
if (access(enginebinary, R_OK|W_OK|X_OK) < 0)
return false; //can't write it. don't try downloading updates.
*COM_SkipPath(enginebinary) = 0;
if (access(enginebinary, R_OK|W_OK) < 0)
return false; //can't write to the containing directory. this does not bode well for moves/overwrites.
return true;
}
#endif

View file

@ -93,6 +93,12 @@ Zone block
void Memory_Init (void); void Memory_Init (void);
void Memory_DeInit(void); void Memory_DeInit(void);
//Prefixes:
//Z - just general 'zone' memory.
//B - allocated memory is not zero-filled.
//F - allocation can return NULL (otherwise sys_errors)
//G - special set of functions with its own rules. Frees must not be mixed.
//Tag - additional special set of functions with their own rules. Frees must not be mixed.
void VARGS Z_Free (void *ptr); void VARGS Z_Free (void *ptr);
void *Z_Malloc (size_t size); // returns 0 filled memory void *Z_Malloc (size_t size); // returns 0 filled memory
void *ZF_Malloc (size_t size); // allowed to fail void *ZF_Malloc (size_t size); // allowed to fail

View file

@ -1354,6 +1354,13 @@ static struct charcache_s *Font_GetChar(font_t *f, unsigned int codepoint)
return &tc; return &tc;
} }
if (charidx == 0x00a0) //nbsp
{
c = Font_GetCharIfLoaded(f, ' ');
if (c)
return c;
}
//not cached, can't get. //not cached, can't get.
c = Font_TryLoadGlyph(f, charidx); c = Font_TryLoadGlyph(f, charidx);

View file

@ -4365,7 +4365,7 @@ void Heightmap_LightPointValues (model_t *mod, const vec3_t point, vec3_t res_di
void Heightmap_StainNode (mnode_t *node, float *parms) void Heightmap_StainNode (mnode_t *node, float *parms)
{ {
} }
void Heightmap_MarkLights (dlight_t *light, int bit, mnode_t *node) void Heightmap_MarkLights (dlight_t *light, dlightbitmask_t bit, mnode_t *node)
{ {
} }

View file

@ -590,7 +590,7 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl
return; return;
} }
if (!model->animcache[sequence->seqindex]) if (!model->animcache[sequence->seqindex])
model->animcache[sequence->seqindex] = FS_LoadMallocGroupFile(model->memgroup, sequencedata->name+32, &fz); model->animcache[sequence->seqindex] = FS_LoadMallocGroupFile(model->memgroup, sequencedata->name+32, &fz, true);
if (!model->animcache[sequence->seqindex] || model->animcache[sequence->seqindex]->magic != (('I'<<0)|('D'<<8)|('S'<<16)|('Q'<<24)) || model->animcache[sequence->seqindex]->version != 10) if (!model->animcache[sequence->seqindex] || model->animcache[sequence->seqindex]->magic != (('I'<<0)|('D'<<8)|('S'<<16)|('Q'<<24)) || model->animcache[sequence->seqindex]->version != 10)
{ {
Sys_Error("Unable to load %s\n", sequencedata->name+32); Sys_Error("Unable to load %s\n", sequencedata->name+32);

View file

@ -1159,7 +1159,7 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b)
char altname[MAX_QPATH]; char altname[MAX_QPATH];
Q_snprintfz(altname, sizeof(altname), "%s.%s", mdlbase, token); Q_snprintfz(altname, sizeof(altname), "%s.%s", mdlbase, token);
TRACE(("Mod_LoadModel: Trying to load (replacement) model \"%s\"\n", altname)); TRACE(("Mod_LoadModel: Trying to load (replacement) model \"%s\"\n", altname));
buf = (unsigned *)FS_LoadMallocFile (altname, &filesize); buf = (unsigned *)FS_LoadMallocGroupFile(NULL, altname, &filesize, true);
if (buf) if (buf)
Q_strncpyz(mod->name, altname, sizeof(mod->name)); Q_strncpyz(mod->name, altname, sizeof(mod->name));
@ -1167,7 +1167,7 @@ static void Mod_LoadModelWorker (void *ctx, void *data, size_t a, size_t b)
else else
{ {
TRACE(("Mod_LoadModel: Trying to load model \"%s\"\n", mod->publicname)); TRACE(("Mod_LoadModel: Trying to load model \"%s\"\n", mod->publicname));
buf = (unsigned *)FS_LoadMallocFile (mod->publicname, &filesize); buf = (unsigned *)FS_LoadMallocGroupFile(NULL, mod->publicname, &filesize, true);
if (buf) if (buf)
Q_strncpyz(mod->name, mod->publicname, sizeof(mod->name)); Q_strncpyz(mod->name, mod->publicname, sizeof(mod->name));
else if (!buf) else if (!buf)
@ -1682,7 +1682,7 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base,
Q_snprintfz(litname, sizeof(litname), litnames[best].pattern, litbase); Q_snprintfz(litname, sizeof(litname), litnames[best].pattern, litbase);
else else
Q_snprintfz(litname, sizeof(litname), litnames[best].pattern, litbasep); Q_snprintfz(litname, sizeof(litname), litnames[best].pattern, litbasep);
litdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, litname, &litsize); litdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, litname, &litsize, false);
} }
else else
{ {
@ -1832,7 +1832,7 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base,
Q_strncpyz(luxname, loadmodel->name, sizeof(luxname)); Q_strncpyz(luxname, loadmodel->name, sizeof(luxname));
COM_StripExtension(loadmodel->name, luxname, sizeof(luxname)); COM_StripExtension(loadmodel->name, luxname, sizeof(luxname));
COM_DefaultExtension(luxname, ".lux", sizeof(luxname)); COM_DefaultExtension(luxname, ".lux", sizeof(luxname));
luxdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, luxname, &luxsz); luxdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, luxname, &luxsz, false);
luxtmp = false; luxtmp = false;
} }
if (!luxdata) if (!luxdata)
@ -1841,14 +1841,14 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base,
COM_StripExtension(COM_SkipPath(loadmodel->name), luxname+5, sizeof(luxname)-5); COM_StripExtension(COM_SkipPath(loadmodel->name), luxname+5, sizeof(luxname)-5);
Q_strncatz(luxname, ".lux", sizeof(luxname)); Q_strncatz(luxname, ".lux", sizeof(luxname));
luxdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, luxname, &luxsz); luxdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, luxname, &luxsz, false);
luxtmp = false; luxtmp = false;
} }
if (!luxdata) //dp... if (!luxdata) //dp...
{ {
COM_StripExtension(loadmodel->name, luxname, sizeof(luxname)); COM_StripExtension(loadmodel->name, luxname, sizeof(luxname));
COM_DefaultExtension(luxname, ".dlit", sizeof(luxname)); COM_DefaultExtension(luxname, ".dlit", sizeof(luxname));
luxdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, luxname, &luxsz); luxdata = FS_LoadMallocGroupFile(&loadmodel->memgroup, luxname, &luxsz, false);
luxtmp = false; luxtmp = false;
} }
//make sure the .lux has the correct size //make sure the .lux has the correct size
@ -1974,8 +1974,8 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base,
overrides->stylesperface = size / (sizeof(*overrides->styles16)*loadmodel->numsurfaces); //rounding issues will be caught on the next line... overrides->stylesperface = size / (sizeof(*overrides->styles16)*loadmodel->numsurfaces); //rounding issues will be caught on the next line...
if (!overrides->stylesperface || size != loadmodel->numsurfaces * sizeof(*overrides->styles16)*overrides->stylesperface) if (!overrides->stylesperface || size != loadmodel->numsurfaces * sizeof(*overrides->styles16)*overrides->stylesperface)
overrides->styles16 = NULL; overrides->styles16 = NULL;
else if (overrides->stylesperface > MAXQ1LIGHTMAPS) else if (overrides->stylesperface > MAXCPULIGHTMAPS)
Con_Printf(CON_WARNING "LMSTYLE16 lump provides %i styles, only the first %i will be used.\n", overrides->stylesperface, MAXQ1LIGHTMAPS); Con_Printf(CON_WARNING "LMSTYLE16 lump provides %i styles, only the first %i will be used.\n", overrides->stylesperface, MAXCPULIGHTMAPS);
} }
if (!overrides->styles8 && !overrides->styles16) if (!overrides->styles8 && !overrides->styles16)
{ //16bit per-face lightmap styles index { //16bit per-face lightmap styles index
@ -1984,8 +1984,8 @@ void Mod_LoadLighting (model_t *loadmodel, bspx_header_t *bspx, qbyte *mod_base,
overrides->stylesperface = size / (sizeof(*overrides->styles8)*loadmodel->numsurfaces); //rounding issues will be caught on the next line... overrides->stylesperface = size / (sizeof(*overrides->styles8)*loadmodel->numsurfaces); //rounding issues will be caught on the next line...
if (!overrides->stylesperface || size != loadmodel->numsurfaces * sizeof(*overrides->styles8)*overrides->stylesperface) if (!overrides->stylesperface || size != loadmodel->numsurfaces * sizeof(*overrides->styles8)*overrides->stylesperface)
overrides->styles8 = NULL; overrides->styles8 = NULL;
else if (overrides->stylesperface > MAXQ1LIGHTMAPS) else if (overrides->stylesperface > MAXCPULIGHTMAPS)
Con_Printf(CON_WARNING "LMSTYLE lump provides %i styles, only the first %i will be used.\n", overrides->stylesperface, MAXQ1LIGHTMAPS); Con_Printf(CON_WARNING "LMSTYLE lump provides %i styles, only the first %i will be used.\n", overrides->stylesperface, MAXCPULIGHTMAPS);
} }
} }

View file

@ -254,7 +254,7 @@ typedef struct {
void (*LightPointValues) (struct model_s *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); void (*LightPointValues) (struct model_s *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir);
void (*StainNode) (struct mnode_s *node, float *parms); void (*StainNode) (struct mnode_s *node, float *parms);
void (*MarkLights) (struct dlight_s *light, int bit, struct mnode_s *node); void (*MarkLights) (struct dlight_s *light, dlightbitmask_t bit, struct mnode_s *node);
int (*ClusterForPoint) (struct model_s *model, const vec3_t point, int *areaout); //pvs index (leaf-1 for q1bsp). may be negative (ie: no pvs). int (*ClusterForPoint) (struct model_s *model, const vec3_t point, int *areaout); //pvs index (leaf-1 for q1bsp). may be negative (ie: no pvs).
qbyte *(*ClusterPVS) (struct model_s *model, int cluster, pvsbuffer_t *pvsbuffer, pvsmerge_t merge); qbyte *(*ClusterPVS) (struct model_s *model, int cluster, pvsbuffer_t *pvsbuffer, pvsmerge_t merge);
@ -437,20 +437,22 @@ typedef struct msurface_s
batch_t *sbatch; batch_t *sbatch;
mtexinfo_t *texinfo; mtexinfo_t *texinfo;
int visframe; // should be drawn when node is crossed int visframe; // should be drawn when node is crossed
#ifdef RTLIGHTS
int shadowframe; int shadowframe;
int clipcount; #endif
// int clipcount;
// legacy lighting info // legacy lighting info
dlightbitmask_t dlightbits;
int dlightframe; int dlightframe;
int dlightbits; qboolean cached_dlight; // true if dynamic light in cache
//static lighting //static lighting
int lightmaptexturenums[MAXRLIGHTMAPS]; //rbsp+fbsp formats have multiple lightmaps int lightmaptexturenums[MAXRLIGHTMAPS]; //rbsp+fbsp formats have multiple lightmaps
lightstyleindex_t styles[MAXQ1LIGHTMAPS]; lightstyleindex_t styles[MAXCPULIGHTMAPS];
qbyte vlstyles[MAXRLIGHTMAPS]; qbyte vlstyles[MAXRLIGHTMAPS];
int cached_light[MAXQ1LIGHTMAPS]; // values currently used in lightmap int cached_light[MAXCPULIGHTMAPS]; // values currently used in lightmap
int cached_colour[MAXQ1LIGHTMAPS]; // values currently used in lightmap int cached_colour[MAXCPULIGHTMAPS]; // values currently used in lightmap
qboolean cached_dlight; // true if dynamic light in cache
#ifndef NOSTAINS #ifndef NOSTAINS
qboolean stained; qboolean stained;
#endif #endif
@ -565,7 +567,7 @@ void Fragment_ClipPoly(fragmentdecal_t *dec, int numverts, float *inverts, shade
size_t Fragment_ClipPlaneToBrush(vecV_t *points, size_t maxpoints, void *planes, size_t planestride, size_t numplanes, vec4_t face); size_t Fragment_ClipPlaneToBrush(vecV_t *points, size_t maxpoints, void *planes, size_t planestride, size_t numplanes, vec4_t face);
void Mod_ClipDecal(struct model_s *mod, vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangent2, float size, unsigned int surfflagmask, unsigned int surflagmatch, void (*callback)(void *ctx, vec3_t *fte_restrict points, size_t numpoints, shader_t *shader), void *ctx); void Mod_ClipDecal(struct model_s *mod, vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangent2, float size, unsigned int surfflagmask, unsigned int surflagmatch, void (*callback)(void *ctx, vec3_t *fte_restrict points, size_t numpoints, shader_t *shader), void *ctx);
void Q1BSP_MarkLights (dlight_t *light, int bit, mnode_t *node); void Q1BSP_MarkLights (dlight_t *light, dlightbitmask_t bit, mnode_t *node);
void GLQ1BSP_LightPointValues(struct model_s *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); void GLQ1BSP_LightPointValues(struct model_s *model, const vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir);
qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, const vec3_t p1, const vec3_t p2, unsigned int hitcontents, struct trace_s *trace); qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, const vec3_t p1, const vec3_t p2, unsigned int hitcontents, struct trace_s *trace);

View file

@ -2521,7 +2521,7 @@ static int GLRecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
{ {
case LM_E5BGR9: case LM_E5BGR9:
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2; lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
unsigned int l = *(unsigned int*)lightmap; unsigned int l = *(unsigned int*)lightmap;
scale = d_lightstylevalue[surf->styles[maps]]; scale = d_lightstylevalue[surf->styles[maps]];
@ -2534,7 +2534,7 @@ static int GLRecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
break; break;
case LM_RGB8: case LM_RGB8:
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3; lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]; scale = d_lightstylevalue[surf->styles[maps]];
r += max3(lightmap[0],lightmap[1],lightmap[2]) * scale; r += max3(lightmap[0],lightmap[1],lightmap[2]) * scale;
@ -2543,7 +2543,7 @@ static int GLRecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
break; break;
case LM_L8: case LM_L8:
lightmap += dt * ((surf->extents[0]>>surf->lmshift)+1) + ds; lightmap += dt * ((surf->extents[0]>>surf->lmshift)+1) + ds;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]; scale = d_lightstylevalue[surf->styles[maps]];
r += *lightmap * scale; r += *lightmap * scale;
@ -2695,7 +2695,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2; lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2;
deluxmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<4; deluxmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<4;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
unsigned int lm = *(unsigned int*)lightmap; unsigned int lm = *(unsigned int*)lightmap;
scale = d_lightstylevalue[surf->styles[maps]]*overbright; scale = d_lightstylevalue[surf->styles[maps]]*overbright;
@ -2720,7 +2720,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3; lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3;
deluxmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3; deluxmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]*overbright; scale = d_lightstylevalue[surf->styles[maps]]*overbright;
@ -2743,7 +2743,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds); lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds);
deluxmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3; deluxmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]*overbright; scale = d_lightstylevalue[surf->styles[maps]]*overbright;
@ -2770,7 +2770,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t
{ {
case LM_E5BGR9: case LM_E5BGR9:
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2; lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
unsigned int lm = *(unsigned int*)lightmap; unsigned int lm = *(unsigned int*)lightmap;
scale = d_lightstylevalue[surf->styles[maps]]*overbright; scale = d_lightstylevalue[surf->styles[maps]]*overbright;
@ -2786,7 +2786,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t
break; break;
case LM_RGB8: case LM_RGB8:
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3; lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]*overbright; scale = d_lightstylevalue[surf->styles[maps]]*overbright;
@ -2800,7 +2800,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, const vec3_t
break; break;
case LM_L8: case LM_L8:
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds); lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds);
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++) for (maps = 0 ; maps < MAXCPULIGHTMAPS && surf->styles[maps] != INVALID_LIGHTSTYLE ; maps++)
{ {
scale = d_lightstylevalue[surf->styles[maps]]*overbright; scale = d_lightstylevalue[surf->styles[maps]]*overbright;

View file

@ -217,7 +217,7 @@ static float Com_FloatArgument(const char *shadername, char *arg, size_t arglen,
#define HASH_SIZE 128 #define HASH_SIZE 128
#define SPF_DEFAULT 0u /*quake3/fte internal*/ #define SPF_DEFAULT 0u /*quake3/fte internal*/
#define SPF_PROGRAMIFY (1u<<0) /*quake3/fte internal*/ #define SPF_PROGRAMIFY (1u<<0) /*automatically replace known glsl, pulling in additional textures+effects from a single primary pass*/
#define SPF_DOOM3 (1u<<1) /*any commands, args, etc, should be interpretted according to doom3's norms*/ #define SPF_DOOM3 (1u<<1) /*any commands, args, etc, should be interpretted according to doom3's norms*/
typedef struct shaderparsestate_s typedef struct shaderparsestate_s

View file

@ -308,8 +308,8 @@ typedef struct llightinfo_s
{ {
struct relight_ctx_s *ctx; //relight context, shared between threads. struct relight_ctx_s *ctx; //relight context, shared between threads.
vec3_t lightmaps[MAXQ1LIGHTMAPS][SINGLEMAP]; vec3_t lightmaps[MAXCPULIGHTMAPS][SINGLEMAP];
vec3_t lightnorm[MAXQ1LIGHTMAPS][SINGLEMAP]; vec3_t lightnorm[MAXCPULIGHTMAPS][SINGLEMAP];
int numlightstyles; int numlightstyles;
vec_t *light; vec_t *light;
vec_t facedist; vec_t facedist;
@ -325,7 +325,7 @@ typedef struct llightinfo_s
vec_t exactmins[2], exactmaxs[2]; vec_t exactmins[2], exactmaxs[2];
int texmins[2], texsize[2]; int texmins[2], texsize[2];
int lightstyles[MAXQ1LIGHTMAPS]; int lightstyles[MAXCPULIGHTMAPS];
} llightinfo_t; } llightinfo_t;
const size_t lightthreadctxsize = sizeof(llightinfo_t); const size_t lightthreadctxsize = sizeof(llightinfo_t);
@ -628,7 +628,7 @@ static void SingleLightFace (mentity_t *light, llightinfo_t *l)
if (mapnum == l->numlightstyles) if (mapnum == l->numlightstyles)
{ // init a new light map { // init a new light map
#ifdef UTILITY #ifdef UTILITY
if (mapnum == MAXQ1LIGHTMAPS) if (mapnum == MAXCPULIGHTMAPS)
{ {
printf ("WARNING: Too many light styles on a face\n"); printf ("WARNING: Too many light styles on a face\n");
return; return;
@ -715,7 +715,7 @@ static void FixMinlight (llightinfo_t *l)
} }
if (i == l->numlightstyles) if (i == l->numlightstyles)
{ {
if (l->numlightstyles == MAXQ1LIGHTMAPS) if (l->numlightstyles == MAXCPULIGHTMAPS)
return; // oh well.. return; // oh well..
for (j=0 ; j<l->numsurfpt ; j++) for (j=0 ; j<l->numsurfpt ; j++)
{ {
@ -771,7 +771,7 @@ static unsigned int PackE5BRG9(vec3_t rgb)
LightFace LightFace
============ ============
*/ */
void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *l, lightstyleindex_t surf_styles[MAXQ1LIGHTMAPS], unsigned int *surf_expsamples, qbyte *surf_rgbsamples, qbyte *surf_deluxesamples, vec4_t surf_plane, vec4_t surf_texplanes[2], vec2_t exactmins, vec2_t exactmaxs, int texmins[2], int texsize[2], float lmscale) void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *l, lightstyleindex_t surf_styles[MAXCPULIGHTMAPS], unsigned int *surf_expsamples, qbyte *surf_rgbsamples, qbyte *surf_deluxesamples, vec4_t surf_plane, vec4_t surf_texplanes[2], vec2_t exactmins, vec2_t exactmaxs, int texmins[2], int texsize[2], float lmscale)
{ {
int s, t; int s, t;
int i,c,ch; int i,c,ch;
@ -820,7 +820,7 @@ void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *l, lightstylein
i = 0; i = 0;
#ifndef UTILITY #ifndef UTILITY
for (; surf_styles[i] != INVALID_LIGHTSTYLE && i < MAXQ1LIGHTMAPS; i++) for (; surf_styles[i] != INVALID_LIGHTSTYLE && i < MAXCPULIGHTMAPS; i++)
{ {
l->lightstyles[i] = surf_styles[i]; l->lightstyles[i] = surf_styles[i];
memset(&l->lightmaps[i], 0, sizeof(l->lightmaps[i][0])*l->numsurfpt); memset(&l->lightmaps[i], 0, sizeof(l->lightmaps[i][0])*l->numsurfpt);
@ -828,7 +828,7 @@ void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *l, lightstylein
} }
#endif #endif
l->numlightstyles = i; l->numlightstyles = i;
for ( ; i<MAXQ1LIGHTMAPS ; i++) for ( ; i<MAXCPULIGHTMAPS ; i++)
l->lightstyles[i] = INVALID_LIGHTSTYLE; l->lightstyles[i] = INVALID_LIGHTSTYLE;
// //
@ -853,7 +853,7 @@ void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *l, lightstylein
// //
// save out the values // save out the values
// //
for (i=0 ; i <MAXQ1LIGHTMAPS ; i++) for (i=0 ; i <MAXCPULIGHTMAPS ; i++)
surf_styles[i] = l->lightstyles[i]; surf_styles[i] = l->lightstyles[i];

View file

@ -4921,7 +4921,7 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string));
// externs->Printf ("to build a clean data tree: qcc -copy <srcdir> <destdir>\n"); // externs->Printf ("to build a clean data tree: qcc -copy <srcdir> <destdir>\n");
// externs->Printf ("to build a clean pak file: qcc -pak <srcdir> <packfile>\n"); // externs->Printf ("to build a clean pak file: qcc -pak <srcdir> <packfile>\n");
// externs->Printf ("to bsp all bmodels: qcc -bspmodels <gamedir>\n"); // externs->Printf ("to bsp all bmodels: qcc -bspmodels <gamedir>\n");
externs->Printf ("-Kwasm causes FTEQCC to dump all asm to qc.asm\n"); externs->Printf ("-Fwasm causes FTEQCC to dump all asm to qc.asm\n");
externs->Printf ("-O0 to disable optimisations\n"); externs->Printf ("-O0 to disable optimisations\n");
externs->Printf ("-O1 to optimise for size\n"); externs->Printf ("-O1 to optimise for size\n");
externs->Printf ("-O2 to optimise more - some behaviours may change\n"); externs->Printf ("-O2 to optimise more - some behaviours may change\n");

View file

@ -8606,17 +8606,6 @@ static void QCBUILTIN PF_h2rain_go(pubprogfuncs_t *prinst, struct globalvars_s *
SV_MulticastProtExt (NULL, MULTICAST_ALL, pr_global_struct->dimension_send, 0, 0); SV_MulticastProtExt (NULL, MULTICAST_ALL, pr_global_struct->dimension_send, 0, 0);
} }
static void QCBUILTIN PF_h2StopSound(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int channel;
edict_t *entity;
entity = G_EDICT(prinst, OFS_PARM0);
channel = G_FLOAT(OFS_PARM1);
SVQ1_StartSound (NULL, (wedict_t*)entity, channel, NULL, 1, 0, 0, 0, CF_SV_RELIABLE);
}
static void QCBUILTIN PF_h2updatesoundpos(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_h2updatesoundpos(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
Con_DPrintf("FTE-H2 FIXME: updatesoundpos not implemented\n"); Con_DPrintf("FTE-H2 FIXME: updatesoundpos not implemented\n");
@ -8639,6 +8628,13 @@ static void QCBUILTIN PF_h2getstring(pubprogfuncs_t *prinst, struct globalvars_s
RETURN_PSTRING(s); RETURN_PSTRING(s);
} }
#endif #endif
static void QCBUILTIN PF_StopSound(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
edict_t *entity = G_EDICT(prinst, OFS_PARM0);
int channel = G_FLOAT(OFS_PARM1);
SVQ1_StartSound (NULL, (wedict_t*)entity, channel, NULL, 1, 0, 0, 0, CF_SV_RELIABLE);
}
static void QCBUILTIN PF_RegisterTEnt(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_RegisterTEnt(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ {
@ -10732,10 +10728,12 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"precache_file4", PF_precache_file, 0, 0, 103, 0}, {"precache_file4", PF_precache_file, 0, 0, 103, 0},
{"dowhiteflash", PF_h2whiteflash, 0, 0, 104, 0}, {"dowhiteflash", PF_h2whiteflash, 0, 0, 104, 0},
{"updatesoundpos", PF_h2updatesoundpos,0, 0, 105, 0}, {"updatesoundpos", PF_h2updatesoundpos,0, 0, 105, 0},
{"stopsound", PF_h2StopSound, 0, 0, 106, 0}, {"stopsound", PF_StopSound, 0, 0, 106, 0, D("void(entity ent, float channel)", "Terminates playback of sounds on the specified entity-channel. CHAN_AUTO should not be used.")},
{"precache_model4", PF_precache_model, 0, 0, 116, 0},//please don't use... {"precache_model4", PF_precache_model, 0, 0, 116, 0},//please don't use...
{"precache_sound4", PF_precache_sound, 0, 0, 117, 0}, {"precache_sound4", PF_precache_sound, 0, 0, 117, 0},
#else
{"stopsound", PF_StopSound, 0, 0, 0, 0, D("void(entity ent, float channel)", "Terminates playback of sounds on the specified entity-channel. CHAN_AUTO should not be used.")},
#endif #endif
{"tracebox", PF_traceboxdp, 0, 0, 0, 90, D("void(vector start, vector mins, vector maxs, vector end, float nomonsters, entity ent)", "Exactly like traceline, but a box instead of a uselessly thin point. Acceptable sizes are limited by bsp format, q1bsp has strict acceptable size values.")}, {"tracebox", PF_traceboxdp, 0, 0, 0, 90, D("void(vector start, vector mins, vector maxs, vector end, float nomonsters, entity ent)", "Exactly like traceline, but a box instead of a uselessly thin point. Acceptable sizes are limited by bsp format, q1bsp has strict acceptable size values.")},

View file

@ -47,6 +47,7 @@ oh, wait, ktx no longer supports those properly.
13: 2009/june gamecode no longer aware of edict_t data (just 'qc' fields). 13: 2009/june gamecode no longer aware of edict_t data (just 'qc' fields).
14: 2017/march gamedata_t.maxentities added 14: 2017/march gamedata_t.maxentities added
15: 2017/june for-64bit string indirection changes. added GAME_CLEAR_EDICT. 15: 2017/june for-64bit string indirection changes. added GAME_CLEAR_EDICT.
16: wasted_edict_t_size is finally 0
*/ */
#define GAME_API_VERSION 15 #define GAME_API_VERSION 15
#define GAME_API_VERSION_MIN 8 #define GAME_API_VERSION_MIN 8
@ -2279,6 +2280,7 @@ qboolean PR_LoadQ1QVM(void)
gd.maxedicts = MAX_Q1QVM_EDICTS; gd.maxedicts = MAX_Q1QVM_EDICTS;
} }
gd.maxedicts = bound(1, pr_maxedicts.ival, gd.maxedicts); gd.maxedicts = bound(1, pr_maxedicts.ival, gd.maxedicts);
gd.maxedicts = bound(1, gd.maxedicts, MAX_EDICTS);
qvm_api_version = gd.APIversion; qvm_api_version = gd.APIversion;
if (!(GAME_API_VERSION_MIN <= qvm_api_version && qvm_api_version <= GAME_API_VERSION)) if (!(GAME_API_VERSION_MIN <= qvm_api_version && qvm_api_version <= GAME_API_VERSION))

View file

@ -444,7 +444,9 @@ static int QDECL ShowMapListExt (const char *name, qofs_t flags, time_t mtime, v
static void SV_MapList_f(void) static void SV_MapList_f(void)
{ {
COM_EnumerateFiles("maps/*.bsp", ShowMapList, NULL); COM_EnumerateFiles("maps/*.bsp", ShowMapList, NULL);
COM_EnumerateFiles("maps/*.bsp.gz", ShowMapListExt, NULL);
COM_EnumerateFiles("maps/*.map", ShowMapListExt, NULL); COM_EnumerateFiles("maps/*.map", ShowMapListExt, NULL);
COM_EnumerateFiles("maps/*.map.gz", ShowMapListExt, NULL);
COM_EnumerateFiles("maps/*.cm", ShowMapList, NULL); COM_EnumerateFiles("maps/*.cm", ShowMapList, NULL);
COM_EnumerateFiles("maps/*.hmp", ShowMapList, NULL); COM_EnumerateFiles("maps/*.hmp", ShowMapList, NULL);
} }
@ -474,7 +476,9 @@ static void SV_Map_c(int argn, const char *partial, struct xcommandargcompletion
if (argn == 1) if (argn == 1)
{ {
COM_EnumerateFiles(va("maps/%s*.bsp", partial), CompleteMapList, ctx); COM_EnumerateFiles(va("maps/%s*.bsp", partial), CompleteMapList, ctx);
COM_EnumerateFiles(va("maps/%s*.bsp.gz", partial), CompleteMapListExt, ctx);
COM_EnumerateFiles(va("maps/%s*.map", partial), CompleteMapListExt, ctx); COM_EnumerateFiles(va("maps/%s*.map", partial), CompleteMapListExt, ctx);
COM_EnumerateFiles(va("maps/%s*.map.gz", partial), CompleteMapListExt, ctx);
COM_EnumerateFiles(va("maps/%s*.cm", partial), CompleteMapList, ctx); COM_EnumerateFiles(va("maps/%s*.cm", partial), CompleteMapList, ctx);
COM_EnumerateFiles(va("maps/%s*.hmp", partial), CompleteMapList, ctx); COM_EnumerateFiles(va("maps/%s*.hmp", partial), CompleteMapList, ctx);
} }
@ -718,7 +722,7 @@ void SV_Map_f (void)
else else
#endif #endif
{ {
char *exts[] = {"maps/%s", "maps/%s.bsp", "maps/%s.cm", "maps/%s.hmp", /*"maps/%s.map",*/ /*"maps/%s.ent",*/ NULL}; char *exts[] = {"maps/%s", "maps/%s.bsp", "maps/%s.bsp.gz", "maps/%s.cm", "maps/%s.hmp", /*"maps/%s.map",*/ /*"maps/%s.ent",*/ NULL};
int i, j; int i, j;
for (i = 0; exts[i]; i++) for (i = 0; exts[i]; i++)

View file

@ -1002,7 +1002,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents,
{ {
//.map is commented out because quite frankly, they're a bit annoying when the engine loads the gpled start.map when really you wanted to just play the damn game intead of take it apart. //.map is commented out because quite frankly, they're a bit annoying when the engine loads the gpled start.map when really you wanted to just play the damn game intead of take it apart.
//if you want to load a .map, just use 'map foo.map' instead. //if you want to load a .map, just use 'map foo.map' instead.
char *exts[] = {"maps/%s", "maps/%s.bsp", "maps/%s.cm", "maps/%s.hmp", /*"maps/%s.map",*/ NULL}; char *exts[] = {"maps/%s", "maps/%s.bsp", "maps/%s.cm", "maps/%s.hmp", /*"maps/%s.map",*/ "maps/%s.bsp.gz", NULL};
int depth, bestdepth; int depth, bestdepth;
flocation_t loc; flocation_t loc;
time_t filetime; time_t filetime;
@ -1244,7 +1244,6 @@ MSV_OpenUserDatabase();
else if (svs.gametype == GT_QUAKE2) else if (svs.gametype == GT_QUAKE2)
{ {
int subs; int subs;
extern int map_checksum;
extern cvar_t sv_airaccelerate; extern cvar_t sv_airaccelerate;
sv.stringsalloced = true; sv.stringsalloced = true;
@ -1256,10 +1255,7 @@ MSV_OpenUserDatabase();
sv.strings.configstring[Q2CS_AIRACCEL] = Z_StrDup("0"); sv.strings.configstring[Q2CS_AIRACCEL] = Z_StrDup("0");
// init map checksum config string but only for Q2/Q3 maps // init map checksum config string but only for Q2/Q3 maps
if (sv.world.worldmodel->fromgame == fg_quake2 || sv.world.worldmodel->fromgame == fg_quake3) sv.strings.configstring[Q2CS_MAPCHECKSUM] = Z_StrDup(va("%i", sv.world.worldmodel->checksum));
sv.strings.configstring[Q2CS_MAPCHECKSUM] = Z_StrDup(va("%i", map_checksum));
else
sv.strings.configstring[Q2CS_MAPCHECKSUM] = Z_StrDup("0");
subs = sv.world.worldmodel->numsubmodels; subs = sv.world.worldmodel->numsubmodels;
if (subs > MAX_PRECACHE_MODELS-1) if (subs > MAX_PRECACHE_MODELS-1)

View file

@ -3510,11 +3510,13 @@ static qboolean Rcon_Validate (void)
intptr_t timediff; intptr_t timediff;
qbyte b; qbyte b;
const hashfunc_t *hashfunc = &hash_sha1;
void *hashctx = alloca(hashfunc->contextsize);
const size_t digestsize = 20; const size_t digestsize = 20;
size_t i, k; size_t i, k;
unsigned char digest[512]; unsigned char digest[512];
const unsigned char **tokens = alloca(sizeof(*tokens)*(Cmd_Argc()*2+5)); //overallocation in case argc is 0. const unsigned char **tokens = alloca(sizeof(*tokens)*(Cmd_Argc()*2+5)); //overallocation in case argc is 0.
size_t *toksizes = alloca(sizeof(*toksizes)*(Cmd_Argc()*2+5)); //overallocation in case argc is 0.
if (strlen(pass) > digestsize*2) if (strlen(pass) > digestsize*2)
{ {
for (i = 0; pass[digestsize*2+i] && i < sizeof(time_t)*2; i++) for (i = 0; pass[digestsize*2+i] && i < sizeof(time_t)*2; i++)
@ -3539,20 +3541,20 @@ static qboolean Rcon_Validate (void)
tokens[5+i*2+0] = Cmd_Argv(i+2); tokens[5+i*2+0] = Cmd_Argv(i+2);
tokens[5+i*2+1] = " "; //a trailing space is required. tokens[5+i*2+1] = " "; //a trailing space is required.
} }
hashfunc->init(hashctx);
for (k = 0; k < 5+i*2; k++) for (k = 0; k < 5+i*2; k++)
toksizes[k] = strlen(tokens[k]); hashfunc->process(hashctx, tokens[k], strlen(tokens[k]));
if (digestsize > 0 && digestsize == SHA1_m(digest, sizeof(digest), k, tokens, toksizes)) hashfunc->terminate(digest, hashctx);
for (i = 0;;i++)
{ {
for (i = 0;;i++) if (i == digestsize)
{ return true;
if (i == digestsize) if (!pass[i*2+0] || !pass[i*2+1])
return true; break; //premature termination
if (!pass[i*2+0] || !pass[i*2+1]) b = dehex(pass[i*2+0])*16+dehex(pass[i*2+1]);
break; //premature termination if (b != digest[i])
b = dehex(pass[i*2+0])*16+dehex(pass[i*2+1]); break;
if (b != digest[i])
break;
}
} }
} }
} }

View file

@ -43,7 +43,7 @@ typedef struct svm_server_s {
int protover; int protover;
unsigned int clients; unsigned int clients;
unsigned int maxclients; unsigned int maxclients;
qboolean needpass; int needpass;
char hostname[48]; //just for our own listings. char hostname[48]; //just for our own listings.
char mapname[16]; //just for our own listings. char mapname[16]; //just for our own listings.
char gamedir[16]; //again... char gamedir[16]; //again...
@ -551,7 +551,7 @@ vfsfile_t *SVM_GenerateIndex(const char *requesthost, const char *fname)
if (server) if (server)
{ {
QuakeCharsToHTML(hostname, sizeof(hostname), server->hostname, false); QuakeCharsToHTML(hostname, sizeof(hostname), server->hostname, false);
VFS_PRINTF(f, "<tr><td>%s</td><td>%s</td><td>%s%s</td><td>%s</td><td>%s</td><td>%u/%u</td></tr>\n", server->game?server->game->name:"Unknown", NET_AdrToString(tmpbuf, sizeof(tmpbuf), &server->adr), server->needpass?"&#x1F512;":"", hostname, server->gamedir, server->mapname, server->clients, server->maxclients); VFS_PRINTF(f, "<tr><td>%s</td><td>%s</td><td>%s%s</td><td>%s</td><td>%s</td><td>%u/%u</td></tr>\n", server->game?server->game->name:"Unknown", NET_AdrToString(tmpbuf, sizeof(tmpbuf), &server->adr), (server->needpass&1)?"&#x1F512;":"", hostname, server->gamedir, server->mapname, server->clients, server->maxclients);
} }
else else
VFS_PRINTF(f, "<tr><td>?</td><td>%s</td><td>?</td><td>?</td><td>?</td><td>?/?</td></tr>\n", NET_AdrToString(tmpbuf, sizeof(tmpbuf), &adr[count])); VFS_PRINTF(f, "<tr><td>?</td><td>%s</td><td>?</td><td>?</td><td>?</td><td>?/?</td></tr>\n", NET_AdrToString(tmpbuf, sizeof(tmpbuf), &adr[count]));
@ -567,7 +567,19 @@ vfsfile_t *SVM_GenerateIndex(const char *requesthost, const char *fname)
VFS_PRINTF(f, "%s", master_css); VFS_PRINTF(f, "%s", master_css);
if (!strcmp(gamename, "UNKNOWN")) if (!strcmp(gamename, "UNKNOWN"))
VFS_PRINTF(f, "<h1>Firewalled/NATed/Unresponsive/Congested (Misconfigured) Servers</h1>\n"); {
VFS_PRINTF(f, "<h1>Unresponsive Servers</h1>\n");
VFS_PRINTF(f, "These servers have sent a heartbeat but have failed to respond to an appropriate query from a different port. This can happen when:<ul>"
"<li>Server is firewalled and all inbound packets are dropped. Try reconfiguring your firewall to allow packets to that process or port.</li>"
"<li>An intermediate router implements an Address/Port-Dependant-Filtering NAT. Try setting up port forwarding.</li>"
"<li>Outgoing connections are asynchronous with regard to port forwarding. Such servers will show with arbitrary ephemerial ports. Docker: you can supposedly work around this with --net=host.</li>"
"<li>Plain and simple packet loss, servers in this state for less than 5 mins may still be fine.</li>"
"<li>Server crashed or was reconfigured before it could respond.</li>"
"<li>MTU limits with failed defragmentation.</li>"
"<li>Routing table misconfiguration.</li>"
"<li>Other.</li>"
"</ul>\n");
}
else else
VFS_PRINTF(f, "<h1>Servers for %s</h1>\n", QuakeCharsToHTML(tmpbuf, sizeof(tmpbuf), gamename, true)); VFS_PRINTF(f, "<h1>Servers for %s</h1>\n", QuakeCharsToHTML(tmpbuf, sizeof(tmpbuf), gamename, true));
@ -587,7 +599,7 @@ vfsfile_t *SVM_GenerateIndex(const char *requesthost, const char *fname)
else else
url = NET_AdrToString(tmpbuf, sizeof(tmpbuf), &server->adr); url = NET_AdrToString(tmpbuf, sizeof(tmpbuf), &server->adr);
QuakeCharsToHTML(hostname, sizeof(hostname), server->hostname, false); QuakeCharsToHTML(hostname, sizeof(hostname), server->hostname, false);
VFS_PRINTF(f, "<tr><td>%s</td><td>%s%s</td><td>%s</td><td>%s</td><td>%u/%u</td></tr>\n", url, server->needpass?"&#x1F512;":"", hostname, server->gamedir, server->mapname, server->clients, server->maxclients); VFS_PRINTF(f, "<tr><td>%s</td><td>%s%s</td><td>%s</td><td>%s</td><td>%u/%u</td></tr>\n", url, (server->needpass&1)?"&#x1F512;":"", hostname, server->gamedir, server->mapname, server->clients, server->maxclients);
clients += server->clients; clients += server->clients;
maxclients += server->maxclients; maxclients += server->maxclients;
} }
@ -607,7 +619,7 @@ vfsfile_t *SVM_GenerateIndex(const char *requesthost, const char *fname)
for (server = (game?game->firstserver:NULL); server; server = server->next) for (server = (game?game->firstserver:NULL); server; server = server->next)
{ {
if (server->brokerid) if (server->brokerid)
VFS_PRINTF(f, "rtc:///%s \\maxclients\\%u\\clients\\%u\\hostname\\%s\\modname\\%s\\mapname\\%s%s\n", server->brokerid, server->maxclients, server->clients, server->hostname, server->gamedir, server->mapname, server->needpass?"\\needpass\\1":""); VFS_PRINTF(f, "rtc:///%s \\maxclients\\%u\\clients\\%u\\hostname\\%s\\modname\\%s\\mapname\\%s\\needpass\\%i\n", server->brokerid, server->maxclients, server->clients, server->hostname, server->gamedir, server->mapname, server->needpass);
else else
VFS_PRINTF(f, "%s\n", NET_AdrToString(tmpbuf, sizeof(tmpbuf), &server->adr)); VFS_PRINTF(f, "%s\n", NET_AdrToString(tmpbuf, sizeof(tmpbuf), &server->adr));
} }
@ -724,7 +736,7 @@ static svm_server_t *SVM_Heartbeat(const char *gamename, netadr_t *adr, int numc
if (server) if (server)
{ //it still exists, renew it, but don't otherwise care too much. { //it still exists, renew it, but don't otherwise care too much.
server->expiretime = validuntil; server->expiretime = validuntil;
return NULL; return server;
} }
game = SVM_FindGame("UNKNOWN", true); game = SVM_FindGame("UNKNOWN", true);
} }
@ -813,7 +825,7 @@ void SVM_GenChallenge(char *out, size_t outsize, netadr_t *foradr)
} }
//switch net_from's reported connection, so we reply from a different udp socket from the one a packet was received from. //switch net_from's reported connection, so we reply from a different udp socket from the one a packet was received from.
static void SVM_SwitchQuerySocket(void) static qboolean SVM_SwitchQuerySocket(void)
{ {
size_t c; size_t c;
//switch the info query to our other udp socket, so any firewall/nat over the server blocks it. //switch the info query to our other udp socket, so any firewall/nat over the server blocks it.
@ -829,9 +841,10 @@ static void SVM_SwitchQuerySocket(void)
(svm_sockets->conn[c]->addrtype[0] == net_from.type || svm_sockets->conn[c]->addrtype[1] == net_from.type)) (svm_sockets->conn[c]->addrtype[0] == net_from.type || svm_sockets->conn[c]->addrtype[1] == net_from.type))
{ //okay, looks like we should be able to respond on this one. lets see if their firewall stops us from finding out more about them. { //okay, looks like we should be able to respond on this one. lets see if their firewall stops us from finding out more about them.
net_from.connum = c+1; net_from.connum = c+1;
break; return true;
} }
} }
return false;
} }
static void SVM_ProcessUDPPacket(void) static void SVM_ProcessUDPPacket(void)
@ -877,7 +890,7 @@ static void SVM_ProcessUDPPacket(void)
line = MSG_ReadStringLine(); line = MSG_ReadStringLine();
s = COM_Parse(line); s = COM_Parse(line);
if (!strcmp(com_token, "getservers") || !strcmp(com_token, "getserversExt")) if (!strcmp(com_token, "getservers") || !strcmp(com_token, "getserversExt"))
{ //q3 { //q3/dpmaster
sizebuf_t sb; sizebuf_t sb;
int ver; int ver;
char *eos; char *eos;
@ -892,7 +905,7 @@ static void SVM_ProcessUDPPacket(void)
s = COM_ParseOut(s, game, sizeof(game)); s = COM_ParseOut(s, game, sizeof(game));
ver = strtol(game, &eos, 0); ver = strtol(game, &eos, 0);
if (*eos) if (*eos)
{ //not a number, must have been a game name. { //not a number, must have been a dpmaster game name.
s = COM_Parse(s); s = COM_Parse(s);
ver = strtol(com_token, NULL, 0); ver = strtol(com_token, NULL, 0);
} }
@ -955,13 +968,19 @@ static void SVM_ProcessUDPPacket(void)
else else
{ //dp/q3/etc are annoying, but we can query from an emphemerial socket to check NAT rules. { //dp/q3/etc are annoying, but we can query from an emphemerial socket to check NAT rules.
sizebuf_t sb; sizebuf_t sb;
netadr_t a;
char ourchallenge[256]; char ourchallenge[256];
SVM_GenChallenge(ourchallenge, sizeof(ourchallenge), &net_from); SVM_GenChallenge(ourchallenge, sizeof(ourchallenge), &net_from);
svm.total.queries++; svm.total.queries++;
//placeholder listing... //placeholder listing...
SVM_Heartbeat(NULL, &net_from, 0, svm.time + sv_heartbeattimeout.ival); if (SVM_Heartbeat(NULL, &net_from, 0, svm.time + sv_heartbeattimeout.ival))
SVM_SwitchQuerySocket(); a = net_from;
else
a.type = NA_INVALID;
if (!SVM_SwitchQuerySocket())
a.type = NA_INVALID;
memset(&sb, 0, sizeof(sb)); memset(&sb, 0, sizeof(sb));
sb.maxsize = sizeof(net_message_buffer); sb.maxsize = sizeof(net_message_buffer);
@ -970,6 +989,17 @@ static void SVM_ProcessUDPPacket(void)
MSG_WriteString(&sb, va("getinfo %s\n", ourchallenge)); MSG_WriteString(&sb, va("getinfo %s\n", ourchallenge));
sb.cursize--; sb.cursize--;
NET_SendPacket(svm_sockets, sb.cursize, sb.data, &net_from); NET_SendPacket(svm_sockets, sb.cursize, sb.data, &net_from);
if (a.type != NA_INVALID)
{ //they were unknown... send a special getinfo, so we can get their hostname while leaving them as 'unknown'
memset(&sb, 0, sizeof(sb));
sb.maxsize = sizeof(net_message_buffer);
sb.data = net_message_buffer;
MSG_WriteLong(&sb, -1);
MSG_WriteString(&sb, va("getinfo ?%s\n", ourchallenge));
sb.cursize--;
NET_SendPacket(svm_sockets, sb.cursize, sb.data, &a);
}
} }
} }
else if (!strcmp(com_token, "infoResponse")) else if (!strcmp(com_token, "infoResponse"))
@ -978,9 +1008,12 @@ static void SVM_ProcessUDPPacket(void)
int clients; int clients;
const char *game, *chal; const char *game, *chal;
svm_server_t *srv; svm_server_t *srv;
qboolean unknownresp = false;
s = MSG_ReadStringLine(); s = MSG_ReadStringLine();
svm.total.heartbeats++; svm.total.heartbeats++;
chal = Info_ValueForKey(s, "challenge"); chal = Info_ValueForKey(s, "challenge");
unknownresp = *chal=='?';
chal += unknownresp?1:0;
SVM_GenChallenge(ourchallenge, sizeof(ourchallenge), &net_from); SVM_GenChallenge(ourchallenge, sizeof(ourchallenge), &net_from);
if (!strcmp(chal, ourchallenge)) if (!strcmp(chal, ourchallenge))
{ {
@ -988,14 +1021,18 @@ static void SVM_ProcessUDPPacket(void)
game = Info_ValueForKey(s, "gamename"); game = Info_ValueForKey(s, "gamename");
if (!*game) if (!*game)
game = QUAKE3PROTOCOLNAME; game = QUAKE3PROTOCOLNAME;
if (unknownresp)
game = NULL; //ignore the gamename and classify it as unknown. this won't break anything if we've already has a proper heartbeat from them.
srv = SVM_Heartbeat(game, &net_from, clients, svm.time + sv_heartbeattimeout.ival); srv = SVM_Heartbeat(game, &net_from, clients, svm.time + sv_heartbeattimeout.ival);
if (srv) if (srv)
{ {
if (developer.ival) if (developer.ival)
Info_Print(s, "\t"); Info_Print(s, "\t");
srv->protover = atoi(Info_ValueForKey(s, "protocol")); srv->clients = clients;
if (game)
srv->protover = atoi(Info_ValueForKey(s, "protocol"));
srv->maxclients = atoi(Info_ValueForKey(s, "sv_maxclients")); srv->maxclients = atoi(Info_ValueForKey(s, "sv_maxclients"));
srv->needpass = !!atoi(Info_ValueForKey(s, "needpass")); srv->needpass = atoi(Info_ValueForKey(s, "needpass"));
Q_strncpyz(srv->hostname, Info_ValueForKey(s, "hostname"), sizeof(srv->hostname)); Q_strncpyz(srv->hostname, Info_ValueForKey(s, "hostname"), sizeof(srv->hostname));
Q_strncpyz(srv->gamedir, Info_ValueForKey(s, "modname"), sizeof(srv->gamedir)); Q_strncpyz(srv->gamedir, Info_ValueForKey(s, "modname"), sizeof(srv->gamedir));
Q_strncpyz(srv->mapname, Info_ValueForKey(s, "mapname"), sizeof(srv->mapname)); Q_strncpyz(srv->mapname, Info_ValueForKey(s, "mapname"), sizeof(srv->mapname));
@ -1058,7 +1095,7 @@ static void SVM_ProcessUDPPacket(void)
Info_Print(s, "\t"); Info_Print(s, "\t");
srv->protover = 3;//atoi(Info_ValueForKey(s, "protocol")); srv->protover = 3;//atoi(Info_ValueForKey(s, "protocol"));
srv->maxclients = atoi(Info_ValueForKey(s, "maxclients")); srv->maxclients = atoi(Info_ValueForKey(s, "maxclients"));
srv->needpass = !!atoi(Info_ValueForKey(s, "needpass")); srv->needpass = atoi(Info_ValueForKey(s, "needpass"));
Q_strncpyz(srv->hostname, Info_ValueForKey(s, "hostname"), sizeof(srv->hostname)); Q_strncpyz(srv->hostname, Info_ValueForKey(s, "hostname"), sizeof(srv->hostname));
Q_strncpyz(srv->gamedir, Info_ValueForKey(s, "*gamedir"), sizeof(srv->gamedir)); Q_strncpyz(srv->gamedir, Info_ValueForKey(s, "*gamedir"), sizeof(srv->gamedir));
Q_strncpyz(srv->mapname, Info_ValueForKey(s, "map"), sizeof(srv->mapname)); Q_strncpyz(srv->mapname, Info_ValueForKey(s, "map"), sizeof(srv->mapname));

View file

@ -451,7 +451,7 @@ int SV_MVD_GotQTVRequest(vfsfile_t *clientstream, char *headerstart, char *heade
int digest[5]; int digest[5];
Q_snprintfz(hash, sizeof(hash), "%s%s", p->challenge, qtv_password.string); Q_snprintfz(hash, sizeof(hash), "%s%s", p->challenge, qtv_password.string);
SHA1((char*)digest, sizeof(digest), hash, strlen(hash)); CalcHash(&hash_sha1, (char*)digest, sizeof(digest), hash, strlen(hash));
Q_snprintfz(hash, sizeof(hash), "%08X%08X%08X%08X%08X", digest[0], digest[1], digest[2], digest[3], digest[4]); Q_snprintfz(hash, sizeof(hash), "%08X%08X%08X%08X%08X", digest[0], digest[1], digest[2], digest[3], digest[4]);
p->hasauthed = !strcmp(password, hash); p->hasauthed = !strcmp(password, hash);
} }

View file

@ -495,7 +495,7 @@ int main(int argc, const char **argv)
if (argc == 1) if (argc == 1)
{ {
printf("%s input.glsl output.fvb\n"); printf("%s input.glsl output.fvb\n", argv[0]);
return 1; return 1;
} }

View file

@ -4312,9 +4312,11 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
#ifdef VK_EXT_debug_report #ifdef VK_EXT_debug_report
qboolean havedebugreport = false; qboolean havedebugreport = false;
#endif #endif
vkEnumerateInstanceExtensionProperties(NULL, &count, NULL); if (VK_SUCCESS!=vkEnumerateInstanceExtensionProperties(NULL, &count, NULL))
count = 0;
ext = malloc(sizeof(*ext)*count); ext = malloc(sizeof(*ext)*count);
vkEnumerateInstanceExtensionProperties(NULL, &count, ext); if (!ext || VK_SUCCESS!=vkEnumerateInstanceExtensionProperties(NULL, &count, ext))
count = 0;
for (i = 0; i < count && extensions_count < countof(extensions); i++) for (i = 0; i < count && extensions_count < countof(extensions); i++)
{ {
Con_DLPrintf(2, " vki: %s\n", ext[i].extensionName); Con_DLPrintf(2, " vki: %s\n", ext[i].extensionName);

View file

@ -1078,7 +1078,7 @@ void HTTPSV_GetMethod(cluster_t *cluster, oproxy_t *pend)
unsigned char sha1digest[20]; unsigned char sha1digest[20];
char padkey[512]; char padkey[512];
snprintf(padkey, sizeof(padkey), "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", key); snprintf(padkey, sizeof(padkey), "%s258EAFA5-E914-47DA-95CA-C5AB0DC85B11", key);
tobase64(acceptkey, sizeof(acceptkey), sha1digest, SHA1(sha1digest, sizeof(sha1digest), padkey, strlen(padkey))); tobase64(acceptkey, sizeof(acceptkey), sha1digest, CalcHash(&hash_sha1, sha1digest, sizeof(sha1digest), padkey, strlen(padkey)));
snprintf(padkey, sizeof(padkey), snprintf(padkey, sizeof(padkey),
"HTTP/1.1 101 Switching Protocols\r\n" "HTTP/1.1 101 Switching Protocols\r\n"

View file

@ -238,8 +238,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
size_t strlcpy(char *dst, const char *src, size_t siz); size_t strlcpy(char *dst, const char *src, size_t siz);
#define SHA1 SHA1_quake
size_t SHA1(unsigned char *digest, size_t maxdigestsize, const unsigned char *string, size_t stringlen); typedef struct
{
unsigned int digestsize;
unsigned int contextsize; //you need to alloca(te) this much memory...
void (*init) (void *context);
void (*process) (void *context, const void *data, size_t datasize);
void (*terminate) (unsigned char *digest, void *context);
} hashfunc_t;
extern hashfunc_t hash_sha1;
/*extern hashfunc_t hash_sha224;
extern hashfunc_t hash_sha256;
extern hashfunc_t hash_sha384;
extern hashfunc_t hash_sha512;*/
#define HMAC HMAC_quake //stop conflicts...
size_t CalcHash(hashfunc_t *hash, unsigned char *digest, size_t maxdigestsize, const unsigned char *string, size_t stringlen);
size_t HMAC(hashfunc_t *hashfunc, unsigned char *digest, size_t maxdigestsize, const unsigned char *data, size_t datalen, const unsigned char *key, size_t keylen);
#ifdef LIBQTV #ifdef LIBQTV

View file

@ -477,7 +477,7 @@ void Net_SendQTVConnectionRequest(sv_t *qtv, char *authmethod, char *challenge)
str = "PASSWORD: \""; Net_QueueUpstream(qtv, strlen(str), str); str = "PASSWORD: \""; Net_QueueUpstream(qtv, strlen(str), str);
snprintf(hash, sizeof(hash), "%s%s", challenge, qtv->connectpassword); snprintf(hash, sizeof(hash), "%s%s", challenge, qtv->connectpassword);
SHA1((unsigned char*)digest, sizeof(digest), hash, strlen(hash)); CalcHash(&hash_sha1, (unsigned char*)digest, sizeof(digest), hash, strlen(hash));
sprintf(hash, "%08X%08X%8X%08X%08X", digest[0], digest[1], digest[2], digest[3], digest[4]); sprintf(hash, "%08X%08X%8X%08X%08X", digest[0], digest[1], digest[2], digest[3], digest[4]);
str = hash; Net_QueueUpstream(qtv, strlen(str), str); str = hash; Net_QueueUpstream(qtv, strlen(str), str);

View file

@ -1228,11 +1228,11 @@ static int sasl_scram_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize, ha
} }
static int sasl_scramsha1minus_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize) static int sasl_scramsha1minus_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize)
{ {
return sasl_scram_initial(ctx, buf, bufsize, SHA1_m, 20, false); return sasl_scram_initial(ctx, buf, bufsize, &hash_sha1, 20, false);
} }
static int sasl_scramsha1plus_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize) static int sasl_scramsha1plus_initial(struct sasl_ctx_s *ctx, char *buf, int bufsize)
{ {
return sasl_scram_initial(ctx, buf, bufsize, SHA1_m, 20, true); return sasl_scram_initial(ctx, buf, bufsize, &hash_sha1, 20, true);
} }
static void buf_cat(buf_t *buf, char *data, int len) static void buf_cat(buf_t *buf, char *data, int len)
@ -1347,7 +1347,7 @@ static int sasl_scram_challenge(struct sasl_ctx_s *ctx, char *in, int inlen, cha
HMAC(func, clientkey, sizeof(clientkey), "Client Key", strlen("Client Key"), salted_password, digestsize); HMAC(func, clientkey, sizeof(clientkey), "Client Key", strlen("Client Key"), salted_password, digestsize);
//Note: if we wanted to be fancy, we could store both clientkey and serverkey instead of salted_password, but I'm not sure there's all that much point. //Note: if we wanted to be fancy, we could store both clientkey and serverkey instead of salted_password, but I'm not sure there's all that much point.
tmp = clientkey; tmp = clientkey;
func(storedkey, sizeof(storedkey), 1, &tmp, &digestsize); CalcHash(func, storedkey, sizeof(storedkey), tmp, digestsize);
HMAC(func, clientsignature, sizeof(clientsignature), sigkey.buf, sigkey.len, storedkey, digestsize); HMAC(func, clientsignature, sizeof(clientsignature), sigkey.buf, sigkey.len, storedkey, digestsize);
for (i = 0; i < digestsize; i++) for (i = 0; i < digestsize; i++)
@ -3621,7 +3621,7 @@ static qboolean JCL_BuddyVCardReply(jclient_t *jcl, xmltree_t *tree, struct iq_s
free(bi->image); free(bi->image);
free(bi->imagehash); free(bi->imagehash);
free(bi->imagemime); free(bi->imagemime);
SHA1(hash, sizeof(hash), photodata, photosize); CalcHash(&hash_sha1, hash, sizeof(hash), photodata, photosize);
for (i = 0, o = 0; i < sizeof(hash); i++) for (i = 0, o = 0; i < sizeof(hash); i++)
{ {
hasha[o++] = hex[(hash[i]>>4) & 0xf]; hasha[o++] = hex[(hash[i]>>4) & 0xf];
@ -3676,7 +3676,7 @@ static qboolean JCL_MyVCardReply(jclient_t *jcl, xmltree_t *tree, struct iq_s *i
else else
{ {
int photosize = Base64_Decode(photodata, sizeof(photodata), photobinval->body, strlen(photobinval->body)); int photosize = Base64_Decode(photodata, sizeof(photodata), photobinval->body, strlen(photobinval->body));
SHA1(digest, sizeof(digest), photodata, photosize); CalcHash(&hash_sha1, digest, sizeof(digest), photodata, photosize);
if (jcl->vcardphotohashstatus != VCP_KNOWN || memcmp(jcl->vcardphotohash, digest, sizeof(jcl->vcardphotohash))) if (jcl->vcardphotohashstatus != VCP_KNOWN || memcmp(jcl->vcardphotohash, digest, sizeof(jcl->vcardphotohash)))
{ {
memcpy(jcl->vcardphotohash, digest, sizeof(jcl->vcardphotohash)); memcpy(jcl->vcardphotohash, digest, sizeof(jcl->vcardphotohash));
@ -3950,7 +3950,7 @@ char *buildcapshash(jclient_t *jcl)
Q_strlcat(out, caps[i].name, outlen); Q_strlcat(out, caps[i].name, outlen);
Q_strlcat(out, "<", outlen); Q_strlcat(out, "<", outlen);
} }
l = SHA1(digest, sizeof(digest), out, strlen(out)); l = CalcHash(&hash_sha1, digest, sizeof(digest), out, strlen(out));
for (i = 0; i < l; i++) for (i = 0; i < l; i++)
Base64_Byte(digest[i]); Base64_Byte(digest[i]);
Base64_Finish(); Base64_Finish();

View file

@ -63,7 +63,7 @@ void XMPP_FT_Frame(jclient_t *jcl)
//server has accepted us, woo. //server has accepted us, woo.
//sid+requester(them)+target(us) //sid+requester(them)+target(us)
req = va("%s%s%s", ft->sid, ft->with, jcl->fulljid); req = va("%s%s%s", ft->sid, ft->with, jcl->fulljid);
SHA1(digest, sizeof(digest), req, strlen(req)); CalcHash(&hash_sha1, digest, sizeof(digest), req, strlen(req));
//in hex //in hex
for (req = domain, j=0; j < 20; j++) for (req = domain, j=0; j < 20; j++)
{ {