From 26d9d89f24f4dd9cc4d11406e5058f1a7d3882fc Mon Sep 17 00:00:00 2001 From: Spoike Date: Mon, 21 Jun 2021 13:46:23 +0000 Subject: [PATCH] Update infrastruture updates. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5904 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- build_qc.sh | 112 ++++++++++++++++ build_wip.sh | 65 +++------ engine/client/m_download.c | 226 ++++++++++++++++++++++++-------- engine/client/m_options.c | 12 +- engine/client/sys_linux.c | 61 +++++++-- engine/common/fs.h | 1 + fte.m4 | 262 +++++++++++++++++++++++++++++++++++++ quakec/dpsymbols.src | 108 +++++++++++++++ 8 files changed, 729 insertions(+), 118 deletions(-) create mode 100755 build_qc.sh create mode 100644 fte.m4 create mode 100644 quakec/dpsymbols.src diff --git a/build_qc.sh b/build_qc.sh new file mode 100755 index 000000000..31f73a634 --- /dev/null +++ b/build_qc.sh @@ -0,0 +1,112 @@ +#!/bin/bash +#FTEQCC and FTEQW must be defined. +#QSS should be defined... + +BUILDFOLDER=~/htdocs +BUILDLOGFOLDER=$BUILDFOLDER/build_logs + +#this really should use the native cpu type... until then we use 32bit in case anyone's still using a 32bit kernel. +if [ "FTEQW" != "" ]; then + echo "--- QC builds ---" + echo "Making fteextensions.qc" + + BASEDIR=~/.fte + GAMEDIR=fte + mkdir -p $BASEDIR/$GAMEDIR/src + + #generate fte's extensions + CFG=$BASEDIR/fte/minusargsaresilly.cfg + echo "pr_dumpplatform -o fteextensions" > $CFG + echo "pr_dumpplatform -o csqcsysdefs -Tcs" >> $CFG + echo "pr_dumpplatform -o menusysdefs -Tmenu" >> $CFG + $FTEQW -basedir $BASEDIR -nohome -quake -game $GAMEDIR +set snd_device none -nosound +set vid_renderer sv +exec minusargsaresilly.cfg +quit >> /dev/null + + #if we have fteqcc available then try to generate some symbol lists for our generic defs + if [ "$FTEQCC" != "" ]; then + #get QSS to spit out its defs for completeness. + if [ "$QSS" != "" ] && [ -e "$BASEDIR/id1/pak1.pak" ] && [ -e "$QSS" ]; then + CFG=$BASEDIR/$GAMEDIR/gen.cfg + echo "pr_dumpplatform -Oqscsextensions -Tcs" > $CFG + echo "pr_dumpplatform -Oqsextensions -Tss" >> $CFG + echo "pr_dumpplatform -Oqsmenuextensions -Tmenu" >> $CFG + $QSS -dedicated -nohome -game $GAMEDIR -basedir $BASEDIR +exec gen.cfg +quit >>/dev/null + else + echo "QSS not available?" + fi + + if [ ! -e "$BASEDIR/fte/src/dpsymbols.src" ]; then + ln -sr quakec/dpsymbols.src $BASEDIR/$GAMEDIR/src/ + fi + if [ ! -e "$BASEDIR/fte/src/dpdefs/" ]; then + echo "no dpdefs subdir found in $BASEDIR/fte/src/ ... manual intervention required" + fi + + #generate symbol tables from the various engines's defs + ( cd $BASEDIR/$GAMEDIR/src + $FTEQCC -Fdumpsymbols -oqsscs.dat qscsextensions.qc && sort -o qss_cs.sym qsscs.dat.sym + $FTEQCC -Fdumpsymbols -oqssss.dat qsextensions.qc && sort -o qss_ss.sym qssss.dat.sym + $FTEQCC -Fdumpsymbols -oqssmn.dat qsmenuextensions.qc && sort -o qss_menu.sym qssmn.dat.sym + + $FTEQCC -Fdumpsymbols -oftecs.dat -DCSQC fteextensions.qc && sort -o fte_cs.sym ftecs.dat.sym + $FTEQCC -Fdumpsymbols -oftess.dat -DSSQC fteextensions.qc && sort -o fte_ss.sym ftess.dat.sym + $FTEQCC -Fdumpsymbols -oftemn.dat -DMENU fteextensions.qc && sort -o fte_menu.sym ftemn.dat.sym + + $FTEQCC -Fdumpsymbols -odpcs.dat -DCSQC dpsymbols.src && sort -o dp_cs.sym dpcs.dat.sym + $FTEQCC -Fdumpsymbols -odpss.dat -DSSQC dpsymbols.src && sort -o dp_ss.sym dpss.dat.sym + $FTEQCC -Fdumpsymbols -odpmn.dat -DMENU dpsymbols.src && sort -o dp_menu.sym dpmn.dat.sym + ) >>/dev/null + + #generate generic extensions + CFG=$BASEDIR/fte/minusargsaresilly.cfg + echo "pr_dumpplatform -Ocsqc_api -Fdepfilter -Tsimplecs" > $CFG + echo "pr_dumpplatform -Ofte_csqc_api -Fdepfilter -Tcs" >> $CFG + echo "pr_dumpplatform -Odp_csqc_api -Fdepfilter -Tdpcs" >> $CFG + echo "pr_dumpplatform -Ossqc_api -Fdepfilter -Tnq" >> $CFG + echo "pr_dumpplatform -Omenu_api -Fdepfilter -Tmenu" >> $CFG + $FTEQW -basedir $BASEDIR -nohome -quake -game $GAMEDIR +set snd_device none -nosound +set vid_renderer sv +exec minusargsaresilly.cfg +quit >> /dev/null + fi + + #fix up and copy the results somewhere useful + rm $CFG + + mkdir -p $BUILDFOLDER/ftedefs $BUILDFOLDER/genericdefs + mv $BASEDIR/$GAMEDIR/src/fteextensions.qc $BUILDFOLDER/ftedefs + mv $BASEDIR/$GAMEDIR/src/csqcsysdefs.qc $BUILDFOLDER/ftedefs + mv $BASEDIR/$GAMEDIR/src/menusysdefs.qc $BUILDFOLDER/ftedefs + mv $BASEDIR/$GAMEDIR/src/*_api.qc $BUILDFOLDER/genericdefs +fi + + +if [ "$FTEQCC" != "" ]; then + mkdir -p $BUILDFOLDER/csaddon/ + + ( cd quakec/csaddon/src + echo -n "Making csaddon... " + $FTEQCC -srcfile csaddon.src > $BUILDLOGFOLDER/csaddon.txt + if [ $? -eq 0 ]; then + echo "done" + cp ../csaddon.dat $BUILDFOLDER/csaddon/ + cd .. + zip -9 $BUILDFOLDER/csaddon/csaddon.pk3 csaddon.dat + else + echo "failed" + fi + ) + + ( cd quakec/menusys + echo -n "Making menusys... " + $FTEQCC -srcfile menu.src > $BUILDLOGFOLDER/menu.txt + if [ $? -eq 0 ]; then + echo "done" + zip -q -9 -o -r $BUILDFOLDER/csaddon/menusys_src.zip . + cp ../menu.dat $BUILDFOLDER/csaddon/ + cd .. + zip -9 $BUILDFOLDER/csaddon/menusys.pk3 menu.dat + else + echo "failed" + fi + ) +else + echo "Skiping csaddon + qcmenu, no compiler build" +fi + diff --git a/build_wip.sh b/build_wip.sh index e919a7eb5..43eb267ab 100755 --- a/build_wip.sh +++ b/build_wip.sh @@ -300,57 +300,24 @@ if [ -e "$HOME/nocompat_readme.html" ]; then cp $HOME/nocompat_readme.html $BUILDFOLDER/nocompat/README.html fi -#this really should use the native cpu type... until then we use 32bit in case anyone's still using a 32bit kernel. -if [ "$BUILD_LINUXx86" != "n" ]; then - echo "--- QC builds ---" - rm -rf $QCCBUILDFOLDER 2>&1 - mkdir -p $QCCBUILDFOLDER - if [ -e "$BUILDFOLDER/linux_x86/fteqw32" ]; then - echo "Making fteextensions.qc" - mkdir -p ~/.fte/fte - echo "pr_dumpplatform -o fteextensions" > ~/.fte/fte/minusargsaresilly.cfg - echo "pr_dumpplatform -o csqcsysdefs -Tcs" >> ~/.fte/fte/minusargsaresilly.cfg - echo "pr_dumpplatform -o menusysdefs -Tmenu" >> ~/.fte/fte/minusargsaresilly.cfg - $BUILDFOLDER/linux_x86/fteqw32 -basedir ~/.fte -nohome -quake +set snd_device none -nosound +set vid_renderer sv +exec minusargsaresilly.cfg +quit >> /dev/null - mv ~/.fte/fte/src/fteextensions.qc $QCCBUILDFOLDER - mv ~/.fte/fte/src/csqcsysdefs.qc $QCCBUILDFOLDER - mv ~/.fte/fte/src/menusysdefs.qc $QCCBUILDFOLDER - else - echo "Skipping FTE Extensions, no Linux x86 (merged) build located" - fi - if [ -e $BUILDFOLDER/linux_x86/fteqcc32 ]; then - mkdir -p $BUILDFOLDER/csaddon/ - cd $SVNROOT/quakec - cd csaddon/src - echo -n "Making csaddon... " - $BUILDFOLDER/linux_x86/fteqcc32 -srcfile csaddon.src > $BUILDLOGFOLDER/csaddon.txt - if [ $? -eq 0 ]; then - echo "done" - cp ../csaddon.dat $BUILDFOLDER/csaddon/ - cd .. - zip -9 $BUILDFOLDER/csaddon/csaddon.pk3 csaddon.dat - else - echo "failed" - fi - - cd $SVNROOT/quakec - cd menusys - echo -n "Making menusys... " - $BUILDFOLDER/linux_x86/fteqcc32 -srcfile menu.src > $BUILDLOGFOLDER/menu.txt - if [ $? -eq 0 ]; then - echo "done" - zip -q -9 -o -r $BUILDFOLDER/csaddon/menusys_src.zip . - cp ../menu.dat $BUILDFOLDER/csaddon/ - cd .. - zip -9 $BUILDFOLDER/csaddon/menusys.pk3 menu.dat - else - echo "failed" - fi - else - echo "Skiping csaddon + qcmenu, no compiler build" +#call out to build_qc.sh to invoke native builds as appropriate. +case "$(uname -m)" in +x86_64) + if [ "$BUILD_LINUXx64" != "n" ]; then + rm -rf $QCCBUILDFOLDER 2>&1 + mkdir -p $QCCBUILDFOLDER + FTEQCC=$BUILDFOLDER/linux_amd64/fteqcc64 FTEQW=$BUILDFOLDER/linux_amd64/fteqw64 QUAKESPASM=quakespasm-spiked-linux64 ./build_qc.sh fi -fi + ;; +i386 | i486 | i586) + if [ "$BUILD_LINUXx86" != "n" ]; then + rm -rf $QCCBUILDFOLDER 2>&1 + mkdir -p $QCCBUILDFOLDER + FTEQCC=$BUILDFOLDER/linux_x86/fteqcc32 FTEQW=$BUILDFOLDER/linux_x86/fteqw32 QUAKESPASM= ./build_qc.sh + fi + ;; +esac cd $SVNROOT/engine/ svn info > $BUILDFOLDER/version.txt diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 63b2d5a37..e2b1b5ea6 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -15,7 +15,7 @@ #define ENABLEPLUGINSBYDEFAULT //auto-enable plugins that the user installs. this risks other programs installing dlls (but we can't really protect our listing file so this is probably not any worse in practise). #ifdef PACKAGEMANAGER - #if !defined(NOBUILTINMENUS) && !defined(SERVERONLY) + #if !defined(NOBUILTINMENUS) && defined(HAVE_CLIENT) #define DOWNLOADMENU #endif #endif @@ -24,16 +24,10 @@ #include "fs.h" //some extra args for the downloads menu (for the downloads menu to handle engine updates). -#if defined(_DEBUG) || defined(DEBUG) -#define PHPDBG "&dbg=1" -#else -#define PHPDBG -#endif #ifndef SVNREVISION #define SVNREVISION - #endif static char enginerevision[256] = STRINGIFY(SVNREVISION); -#define DOWNLOADABLESARGS PHPDBG @@ -355,7 +349,7 @@ static qboolean PM_PurgeOnDisable(package_t *p) return true; } -void PM_ValidateAuthenticity(package_t *p, enum hashvalidation_e validated) +static void PM_ValidateAuthenticity(package_t *p, enum hashvalidation_e validated) { qbyte hashdata[512]; size_t hashsize = 0; @@ -609,6 +603,14 @@ static qboolean PM_MergePackage(package_t *oldp, package_t *newp) if (ignorefiles || (om && nm)) return false; } + + //packages are merged according to how it should look when its actually installed. + //this means we might be merging two packages from different sources with different installation methods/files/etc... + if ((newp->signature && oldp->signature && strcmp(newp->signature, oldp->signature)) || + (newp->filesha512 && oldp->filesha512 && strcmp(newp->filesha512, oldp->filesha512)) || + (newp->filesha1 && oldp->filesha1 && strcmp(newp->filesha1, oldp->filesha1))) + return false; + for (od = oldp->deps, nd = newp->deps; od && nd; ) { //if its a zip then the 'remote' file list will be blank while the local list is not (we can just keep the local list). @@ -641,10 +643,18 @@ static qboolean PM_MergePackage(package_t *oldp, package_t *newp) if (newp->website){Z_Free(oldp->website); oldp->website = Z_StrDup(newp->website);} if (newp->previewimage){Z_Free(oldp->previewimage); oldp->previewimage = Z_StrDup(newp->previewimage);} - if (newp->signature){Z_Free(oldp->signature); oldp->signature = Z_StrDup(newp->signature);} - if (newp->filesha1){Z_Free(oldp->filesha1); oldp->filesha1 = Z_StrDup(newp->filesha1);} - if (newp->filesha512){Z_Free(oldp->filesha512); oldp->filesha512 = Z_StrDup(newp->filesha512);} - if (newp->filesize){oldp->filesize = newp->filesize;} + //use the new package's auth settings. this affects downloading rather than reactivation. + if (newp->signature || newp->filesha1 || newp->filesha512) + { + Z_Free(oldp->signature); oldp->signature = newp->signature?Z_StrDup(newp->signature):NULL; + Z_Free(oldp->filesha1); oldp->filesha1 = newp->filesha1?Z_StrDup(newp->filesha1):NULL; + Z_Free(oldp->filesha512); oldp->filesha512 = newp->filesha512?Z_StrDup(newp->filesha512):NULL; + oldp->filesize = newp->filesize; + oldp->flags &= ~(DPF_SIGNATUREACCEPTED|DPF_SIGNATUREREJECTED|DPF_SIGNATUREUNKNOWN); + oldp->flags |= newp->flags&(DPF_SIGNATUREACCEPTED|DPF_SIGNATUREREJECTED|DPF_SIGNATUREUNKNOWN); + } + else + oldp->flags &= ~DPF_SIGNATUREACCEPTED; oldp->priority = newp->priority; @@ -883,6 +893,8 @@ static void PM_AddSubList(const char *url, const char *prefix, unsigned int flag pm_source[i].prefix = BZ_Malloc(strlen(prefix)+1); strcpy(pm_source[i].prefix, prefix); + + downloadablessequence++; } } #ifdef WEBCLIENT @@ -1344,6 +1356,8 @@ static qboolean PM_ParsePackageList(const char *f, unsigned int parseflags, cons return forcewrite; //it's not the right version. } + downloadablessequence++; + while(*f) { linestart = f; @@ -1570,6 +1584,7 @@ static int QDECL PM_EnumeratedPlugin (const char *name, qofs_t size, time_t mtim int len, l, a; char *dot; const char *synthver = "??""??"; + char *pkgname; if (!strncmp(name, PLUGINPREFIX, strlen(PLUGINPREFIX))) Q_strncpyz(vmname, name+strlen(PLUGINPREFIX), sizeof(vmname)); else @@ -1614,6 +1629,10 @@ static int QDECL PM_EnumeratedPlugin (const char *name, qofs_t size, time_t mtim } } + pkgname = va("fteplug_%s", vmname); + + if (PM_FindExactPackage(pkgname, NULL, NULL, 0)) + return true; //don't include it if its a dupe anyway. if (PM_FindExactPackage(vmname, NULL, NULL, 0)) return true; //don't include it if its a dupe anyway. //FIXME: should be checking whether there's a package that provides the file... @@ -1623,7 +1642,7 @@ static int QDECL PM_EnumeratedPlugin (const char *name, qofs_t size, time_t mtim p->deps->dtype = DEP_FILE; strcpy(p->deps->name, name); p->arch = Z_StrDup(THISARCH); - p->name = Z_StrDup(vmname); + p->name = Z_StrDup(pkgname); p->title = Z_StrDup(vmname); p->category = Z_StrDup("Plugins/"); p->priority = PM_DEFAULTPRIORITY; @@ -1684,9 +1703,9 @@ static void PM_PreparePackageList(void) if (fs_manifest && fs_manifest->downloadsurl && *fs_manifest->downloadsurl) { if (fs_manifest->security==MANIFEST_SECURITY_NOT) - PM_AddSubList(fs_manifest->downloadsurl, NULL, SRCFL_MANIFEST); //don't trust it, don't even prompt. + PM_AddSubList(fs_manifest->downloadsurl, NULL, SRCFL_MANIFEST|SRCFL_DISABLED); //don't trust it, don't even prompt. else - PM_AddSubList(fs_manifest->downloadsurl, NULL, SRCFL_MANIFEST|SRCFL_ENABLED); //enable it by default. functionality is kinda broken otherwise. + PM_AddSubList(fs_manifest->downloadsurl, NULL, SRCFL_MANIFEST); //enable it by default. functionality is kinda broken otherwise. } #ifdef PLUGINS @@ -2395,7 +2414,7 @@ static void PM_AllowPackageListQuery_Callback(void *ctx, promptbutton_t opt) for (i = 0; i < pm_numsources; i++) { - if (pm_source[i].flags & SRCFL_MANIFEST) + if ((pm_source[i].flags & SRCFL_MANIFEST) && !(pm_source[i].flags & SRCFL_DISABLED)) pm_source[i].flags |= SRCFL_ONCE; } } @@ -2455,7 +2474,7 @@ static void PM_UpdatePackageList(qboolean autoupdate, int retry) if (pm_source[i].status == SRCSTAT_OBTAINED) return; //already successful once. no need to do it again. pm_source[i].flags &= ~SRCFL_ONCE; - pm_source[i].curdl = HTTP_CL_Get(va("%s%s"DOWNLOADABLESARGS, pm_source[i].url, strchr(pm_source[i].url,'?')?"&":"?"), NULL, PM_ListDownloaded); + pm_source[i].curdl = HTTP_CL_Get(pm_source[i].url, NULL, PM_ListDownloaded); if (pm_source[i].curdl) { pm_source[i].curdl->user_num = i; @@ -3205,10 +3224,10 @@ typedef struct { char *fname; qbyte ctx[1]; } hashfile_t; -static int QDECL SHA1File_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestowrite) +static int QDECL HashFile_WriteBytes (struct vfsfile_s *file, const void *buffer, int bytestowrite) { hashfile_t *f = (hashfile_t*)file; - f->hashfunc->process(&f->ctx, buffer, bytestowrite); + f->hashfunc->process(f->ctx, buffer, bytestowrite); if (bytestowrite != VFS_WRITE(f->f, buffer, bytestowrite)) f->fail = true; //something went wrong. if (f->fail) @@ -3216,12 +3235,12 @@ static int QDECL SHA1File_WriteBytes (struct vfsfile_s *file, const void *buffer f->sz += bytestowrite; return bytestowrite; } -static void QDECL SHA1File_Flush (struct vfsfile_s *file) +static void QDECL HashFile_Flush (struct vfsfile_s *file) { hashfile_t *f = (hashfile_t*)file; VFS_FLUSH(f->f); } -static qboolean QDECL SHA1File_Close (struct vfsfile_s *file) +static qboolean QDECL HashFile_Close (struct vfsfile_s *file) { qbyte digest[256]; hashfile_t *f = (hashfile_t*)file; @@ -3229,9 +3248,9 @@ static qboolean QDECL SHA1File_Close (struct vfsfile_s *file) f->fail = true; //something went wrong. f->f = NULL; - f->hashfunc->terminate(digest, &f->ctx); + 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 + Con_Printf("Filesystem problem saving %s during download\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 @@ -3239,20 +3258,27 @@ static qboolean QDECL SHA1File_Close (struct vfsfile_s *file) } else if (memcmp(digest, f->need, f->hashfunc->digestsize)) { + qbyte base64[512]; Con_Printf("Invalid hash for downloaded file %s, try again later?\n", f->fname); + + Base64_EncodeBlock(digest, f->hashfunc->digestsize, base64, sizeof(base64)-1); + base64[sizeof(base64)-1] = 0; + Con_Printf("%s vs", base64); + Base64_EncodeBlock(f->need, f->hashfunc->digestsize, base64, sizeof(base64)-1); + Con_Printf("%s\n", base64); 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) +static vfsfile_t *FS_Hash_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.WriteBytes = HashFile_WriteBytes; + n->pub.Flush = HashFile_Flush; + n->pub.Close = HashFile_Close; n->pub.seekstyle = SS_UNSEEKABLE; n->f = f; n->hashfunc = hashfunc; @@ -3262,7 +3288,7 @@ static vfsfile_t *FS_Sha1_ValidateWrites(vfsfile_t *f, const char *fname, qofs_t Base16_DecodeBlock(hash, n->need, sizeof(n->need)); n->fail = false; - n->hashfunc->init(&n->ctx); + n->hashfunc->init(n->ctx); f = &n->pub; } @@ -3276,23 +3302,28 @@ 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... + 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. //packages without a signature are only allowed under some limited conditions. //basically we only allow meta packages, pk3s, and paks. + //metadata doesn't specify all file names for zips. 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) + return false; + if (!p->gamedir || !*p->gamedir) + return false; + for (dep = p->deps; dep; dep = dep->next) { if (dep->dtype != DEP_FILE) continue; + //only allow .pak/.pk3/.zip without a signature, and only when they have a qhash specified (or the .fmf specified it without a qhash...). COM_FileExtension(dep->name, ext, sizeof(ext)); if ((!stricmp(ext, "pak") || !stricmp(ext, "pk3") || !stricmp(ext, "zip")) && (p->qhash || (p->flags&DPF_MANIFEST))) ; @@ -3464,9 +3495,9 @@ static void PM_StartADownload(void) } if (p->filesha512 && tmpfile) - tmpfile = FS_Sha1_ValidateWrites(tmpfile, p->name, p->filesize, &hash_sha512, p->filesha512); + tmpfile = FS_Hash_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); + tmpfile = FS_Hash_ValidateWrites(tmpfile, p->name, p->filesize, &hash_sha1, p->filesha1); if (tmpfile) { @@ -3824,6 +3855,7 @@ static void PM_AddSubList_Callback(void *ctx, promptbutton_t opt) { PM_AddSubList(ctx, "", SRCFL_USER|SRCFL_ENABLED); PM_WriteInstalledPackages(); + PM_UpdatePackageList(false, 0); } Z_Free(ctx); } @@ -4478,6 +4510,11 @@ void QCBUILTIN PF_cl_getpackagemanagerinfo(pubprogfuncs_t *prinst, struct global enum packagemanagerinfo_e fieldidx = G_INT(OFS_PARM1); package_t *p; G_INT(OFS_RETURN) = 0; + if (packageidx < 0) + return; + if (packageidx == 0) + PM_AreSourcesNew(true); + for (p = availablepackages; p; p = p->next) { if ((p->flags & DPF_HIDDEN) && !(p->flags & (DPF_MARKED|DPF_ENABLED|DPF_PURGE|DPF_CACHED))) @@ -4849,7 +4886,12 @@ static void MD_Source_Draw (int x, int y, struct menucustom_s *c, struct emenu_s { char *text; if (!(pm_source[c->dint].flags & SRCFL_ENABLED)) - Draw_FunStringWidth (x, y, "^&04 ", 48, 2, false); //red + { + if (!(pm_source[c->dint].flags & SRCFL_DISABLED)) + Draw_FunStringWidth (x, y, "??", 48, 2, false); + else + Draw_FunStringWidth (x, y, "^&04 ", 48, 2, false); //red + } else switch(pm_source[c->dint].status) { case SRCSTAT_OBTAINED: @@ -4893,23 +4935,41 @@ static void MD_Source_Draw (int x, int y, struct menucustom_s *c, struct emenu_s break; } - text = va("Source %s", pm_source[c->dint].url); + text = va("%s%s", (pm_source[c->dint].flags & (SRCFL_ENABLED|SRCFL_DISABLED))?"":"^b", + pm_source[c->dint].url); Draw_FunString (x+48, y, text); } static qboolean MD_Source_Key (struct menucustom_s *c, struct emenu_s *m, int key, unsigned int unicode) { if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1) + { + if (pm_source[c->dint].flags & SRCFL_DISABLED) + { + pm_source[c->dint].flags = (pm_source[c->dint].flags&~SRCFL_DISABLED)|SRCFL_ENABLED; + pm_source[c->dint].status = SRCSTAT_UNTRIED; + } + else + { + pm_source[c->dint].flags = (pm_source[c->dint].flags&~SRCFL_ENABLED)|SRCFL_DISABLED; + pm_source[c->dint].status = SRCSTAT_PENDING; + } + PM_WriteInstalledPackages(); + PM_UpdatePackageList(true, 2); + } + if (key == K_DEL || key == K_BACKSPACE) { if (pm_source[c->dint].flags & SRCFL_ENABLED) { pm_source[c->dint].flags = (pm_source[c->dint].flags&~SRCFL_ENABLED)|SRCFL_DISABLED; pm_source[c->dint].status = SRCSTAT_PENDING; } - else + else if (pm_source[c->dint].flags & SRCFL_USER) { - pm_source[c->dint].flags = (pm_source[c->dint].flags&~SRCFL_DISABLED)|SRCFL_ENABLED; - pm_source[c->dint].status = SRCSTAT_UNTRIED; + pm_source[c->dint].flags &= ~(SRCFL_ENABLED|SRCFL_DISABLED); + pm_source[c->dint].flags |= SRCFL_HISTORIC; } + else + return false; //will just be re-added anyway... :( PM_WriteInstalledPackages(); PM_UpdatePackageList(true, 2); } @@ -5123,6 +5183,7 @@ static void MD_Download_UpdateStatus(struct emenu_s *m) int i; unsigned int downloads=0; menucustom_t *c; + qboolean sources; #endif if (info->downloadablessequence != downloadablessequence || !info->populated) @@ -5212,10 +5273,13 @@ static void MD_Download_UpdateStatus(struct emenu_s *m) info->populated = true; MC_AddFrameStart(m, 48); #ifdef WEBCLIENT - for (i = 0; i < pm_numsources; i++) + for (i = 0, sources=false; i < pm_numsources; i++) { if (pm_source[i].flags & SRCFL_HISTORIC) continue; //historic... ignore it. + if (!sources) + MC_AddBufferedText(m, 48, 320-16, y, "Sources", false, true), y += 8; + sources=true; c = MC_AddCustom(m, 0, y, p, i, NULL); c->draw = MD_Source_Draw; c->key = MD_Source_Key; @@ -5228,6 +5292,7 @@ static void MD_Download_UpdateStatus(struct emenu_s *m) } y+=4; //small gap #endif + MC_AddBufferedText(m, 48, 320-16, y, "Options", false, true), y += 8; b = MC_AddCommand(m, 48, 320-16, y, info->applymessage, MD_ApplyDownloads); b->rightalign = false; b->common.tooltip = "Enable/Disable/Download/Delete packages to match any changes made (you will be prompted with a list of the changes that will be made)."; @@ -5254,6 +5319,7 @@ static void MD_Download_UpdateStatus(struct emenu_s *m) y += 8; #endif y+=4; //small gap + MC_AddBufferedText(m, 48, 320-16, y, "Packages", false, true), y += 8; MD_AddItemsToDownloadMenu(m, y, info->pathprefix); if (!m->selecteditem) m->selecteditem = (menuoption_t*)d; @@ -5281,6 +5347,7 @@ void Menu_DownloadStuff_f (void) emenu_t *menu; dlmenu_t *info; + Key_Dest_Remove(kdm_console|kdm_cwindows); menu = M_CreateMenu(sizeof(dlmenu_t)); info = menu->data; @@ -5296,45 +5363,88 @@ void Menu_DownloadStuff_f (void) info->populated = false; //will add any headers as needed } -#ifndef SERVERONLY +#ifdef WEBCLIENT static void PM_ConfirmSource(void *ctx, promptbutton_t button) { size_t i; - if (button == PROMPT_YES || button == PROMPT_NO) + if (button == PROMPT_YES) { for (i = 0; i < pm_numsources; i++) { if (!strcmp(pm_source[i].url, ctx)) { pm_source[i].flags |= (button == PROMPT_YES)?SRCFL_ENABLED:SRCFL_DISABLED; + PM_WriteInstalledPackages(); Menu_Download_Update(); return; } } } + else //cancel or 'customize' + { + for (i = 0; i < pm_numsources; i++) + pm_source[i].flags |= SRCFL_PROMPTED; + + if (button == PROMPT_NO) + Cmd_ExecuteString("menu_download\n", RESTRICT_LOCAL); + } } #endif -//should only be called AFTER the filesystem etc is inited. -void Menu_Download_Update(void) +//given a url, try to chop it down to just a hostname +static const char *PrettyHostFromURL(const char *origurl) { - if (pkg_autoupdate.ival <= 0) - return; + char *url, *end; + url = va("%s", origurl); + if (!strnicmp(url, "https://", 8)) + url+=8; + else if (!strnicmp(url, "http://", 7)) + url+=7; + else + return origurl; - PM_UpdatePackageList(true, 2); + url = va("%s", url); + if (*url == '[') + { //ipv6 host + end = strchr(url+1, ']'); + if (!end) + return origurl; + *end = 0; + } + else + { //strip any resource part. + end = strchr(url, '/'); + if (end) + *end = 0; + //strip any explicit port number. + end = strrchr(url, ':'); + if (end) + *end = 0; + } -#ifndef SERVERONLY - if (fs_manifest && pkg_autoupdate.ival > 0) + return url; +} + +qboolean PM_AreSourcesNew(qboolean doprompt) +{ + qboolean ret = false; +#ifdef WEBCLIENT + if (pkg_autoupdate.ival > 0) { //only prompt if autoupdate is actually enabled. int i; for (i = 0; i < pm_numsources; i++) { if (pm_source[i].flags & SRCFL_HISTORIC) continue; //hidden anyway - if (!(pm_source[i].flags & (SRCFL_ENABLED|SRCFL_DISABLED))) + if (!(pm_source[i].flags & (SRCFL_ENABLED|SRCFL_DISABLED|SRCFL_PROMPTED))) { - Menu_Prompt(PM_ConfirmSource, Z_StrDup(pm_source[i].url), va("Enable update source\n\n^x66F%s", pm_source[i].url), "Enable", "Disable", "Later"); - pm_source[i].flags |= SRCFL_PROMPTED; + ret = true; //something is dirty. + if (doprompt) + { + const char *msg = va("Enable update source\n\n^x66F%s", (pm_source[i].flags&SRCFL_MANIFEST)?PrettyHostFromURL(pm_source[i].url):pm_source[i].url); + Menu_Prompt(PM_ConfirmSource, Z_StrDup(pm_source[i].url), msg, "Enable", "Configure", "Later"); + pm_source[i].flags |= SRCFL_PROMPTED; + } break; } } @@ -5345,6 +5455,16 @@ void Menu_Download_Update(void) }*/ } #endif + return ret; +} + +//should only be called AFTER the filesystem etc is inited. +void Menu_Download_Update(void) +{ + if (pkg_autoupdate.ival <= 0) + return; + + PM_UpdatePackageList(true, 2); } #else void Menu_Download_Update(void) diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 57de8223a..72a37535c 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -2,6 +2,7 @@ #include "quakedef.h" #include "winquake.h" +#include "fs.h" static const char *res4x3[] = @@ -1246,6 +1247,14 @@ static void M_Menu_Preset_Predraw(emenu_t *menu) ((char*)op->button.text)[1] = (preset==0)?'m':'7'; preset--; } +#if defined(WEBCLIENT) && defined(PACKAGEMANAGER) + else if (!strcmp(op->button.command, "menu_download\n")) + { + op->button.text = PM_AreSourcesNew(false)?"^bPackages (New!)":"Packages"; + op->common.posx = op->common.next->common.posx; + op->common.width = 216-op->common.posx; + } +#endif } else if (!filtering) { @@ -1322,7 +1331,7 @@ void M_Menu_Preset_f (void) MB_SPACING(16), MB_CHECKBOXCVARTIP("Auto-save Settings", cfg_save_auto, 1, "If this is disabled, you will need to explicitly save your settings."), #if defined(WEBCLIENT) && defined(PACKAGEMANAGER) - MB_CONSOLECMD("Updates", "menu_download\n", "Configure sources and packages."), + MB_CONSOLECMD("Packages", "menu_download\n", "Configure sources and packages."), #endif MB_SPACING(16), MB_CONSOLECMD("Accept", "menupop\n", "Continue with selected settings."), @@ -4191,7 +4200,6 @@ void M_Menu_ModelViewer_f(void) } #endif -#include "fs.h" static void Mods_Draw(int x, int y, struct menucustom_s *c, struct emenu_s *m) { int i = c->dint; diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c index 19f93e54f..be47a0732 100644 --- a/engine/client/sys_linux.c +++ b/engine/client/sys_linux.c @@ -1102,9 +1102,20 @@ static void DoSign(const char *fname, int signtype) auth = com_argv[i+1]; f = FS_OpenVFS(fname, "rb", FS_SYSTEM); - if (f) + if (f && signtype == -1) + { //just report the qhash + searchpathfuncs_t *search = FS_OpenPackByExtension(f, NULL, fname, fname); + if (search) + { + printf("%#08x", search->GeneratePureCRC(search, 0, 0)); + search->ClosePath(search); + } + else + printf("-"); + } + else if (f) { - hashfunc_t *h = &hash_sha512; + hashfunc_t *h = (signtype==1)?&hash_sha256:&hash_sha512; size_t l, ts = 0; void *ctx = alloca(h->contextsize); qbyte data[65536*16]; @@ -1133,7 +1144,12 @@ static void DoSign(const char *fname, int signtype) sigsize = Crypto_GenerateSignature(digest, h->digestsize, signature, sizeof(signature)); Base64_EncodeBlock(signature, sigsize, base64, sizeof(base64)); - printf("%s\n", base64); + printf("%s", base64); + } + else + { //just spits out the hash + Base16_EncodeBlock(digest, h->digestsize, base64, sizeof(base64)); + printf("%s", base64); } } } @@ -1294,19 +1310,36 @@ int main (int c, const char **v) //begin meta generation helpers //fteqw -privcert privcert.key -pubcert pubcert.key -sign binaryfile.pk3 - i = COM_CheckParm("-sign"); - if (!i) - i = COM_CheckParm("-sign2"); - if (i) { - //init some useless crap - host_parms = parms; - Cvar_Init(); - Memory_Init (); - COM_Init (); + static struct + { + const char *arg; + int type; + } signarg[] = + { + {"-sign", 0}, + {"-sign2", 2}, + {"-qhash", -1}, + {"-sha1", 1}, + {"-sha256", 256}, + {"-sha512", 512}, + }; + int j; + for (j = 0; j < countof(signarg); j++) + { + i = COM_CheckParm(signarg[j].arg); + if (i) + { + //init some useless crap + host_parms = parms; + Cvar_Init(); + Memory_Init (); + COM_Init (); - DoSign(com_argv[i+1], atoi(com_argv[i+0]+5)); - return EXIT_SUCCESS; + DoSign(com_argv[i+1], signarg[j].type); + return EXIT_SUCCESS; + } + } } //end diff --git a/engine/common/fs.h b/engine/common/fs.h index 4552f5a24..5911809a0 100644 --- a/engine/common/fs.h +++ b/engine/common/fs.h @@ -78,6 +78,7 @@ int PM_IsApplying(qboolean listsonly); unsigned int PM_MarkUpdates (void); //mark new/updated packages as needing install. void PM_ApplyChanges(void); //for -install/-doinstall args void PM_ManifestPackage(const char *name, int security); +qboolean PM_AreSourcesNew(qboolean doprompt); qboolean PM_FindUpdatedEngine(char *syspath, size_t syspathsize); //names the engine we should be running void PM_AddManifestPackages(ftemanifest_t *man); void Menu_Download_Update(void); diff --git a/fte.m4 b/fte.m4 new file mode 100644 index 000000000..01f150ded --- /dev/null +++ b/fte.m4 @@ -0,0 +1,262 @@ +dnl +dnl This file will be processed to provide relevant package lists for the various packages built from FTE's source. +dnl The output will need to be combined with any other packages, and then signed for these packages to be considered valid. +dnl Users can add extra sources with the `pkg addsource URL' console command (will show a prompt, to try to avoid exploits). +dnl +define(`DATE',FTE_DATE)dnl +define(`REVISION',FTE_REVISION)dnl +define(`DLSIZE',`esyscmd(`stat --printf="%s" $1')')dnl +define(`SHA512',`esyscmd(`fteqw -sha512 $1')')dnl +define(`URL',`url "$1" + dlsize "DLSIZE($1)" + sha512 "SHA512($1)" ')dnl +define(`CAT',`$1$2$3$4$5$6$7$8$9')dnl +define(`ZIP',`unzipfile "$2" + URL($1$3)')dnl +define(`FILE',`file "$1$2$3$4$5$6$7$8$9"')dnl +define(`WINENGINE',`category "Engine" + ver "REVISION" + gamedir "" + license "GPLv2" + { + arch "win_x86-FTE$1" + FILE(fteqw_,REVISION,_32.exe) + ZIP(win32/,CAT($2,.exe),CAT($2,_win32.zip)) + } + { + arch "win_x64-FTE$1" + FILE(fteqw_,REVISION,_64.exe) + ZIP(win64/,CAT($2,64.exe),CAT($2,_win64.zip)) + }')dnl +define(`LINENGINE2',`{ + arch "linux_amd64-FTE$1" + FILE(fteqw_,REVISION,_64.bin) + ZIP(linux_amd64/,CAT($2,64),$3) + }')dnl +define(`LINENGINE',`LINENGINE2($1,$2,CAT($2_lin64.zip))')dnl +define(`HIDE',)dnl +define(`GAME',`ifelse(FTE_GAME,$1,$2 +,)')dnl +define(`TEST',`ifelse(FTE_TEST,`1',` test "1" +',` test "0" +')')dnl +{ + package "fte_cl" + WINENGINE(-m,fteqw) + LINENGINE(-m,fteqw) + title "CAT(`FTE Engine ',DATE)" + desc "The awesome FTE engine (multi-renderer build)" +TEST()dnl +} +HIDE(` +{ + package "fte_cl_gl" +dnl WINENGINE(-gl,fteglqw) +dnl //don't bother advertising it on linux +dnl title "CAT(`FTE Engine ',DATE,` - OpenGL'") + desc "The awesome FTE engine (OpenGL-only build)" +TEST()dnl +} +{ + package "fte_cl_vk" +dnl WINENGINE(-vk,ftevkqw) +dnl //don't bother advertising it on linux +dnl title "CAT(`FTE Engine ',DATE,` - Vulkan')" + desc "The awesome FTE engine (Vulkan-only build)" +TEST()dnl +} +{ + package "fte_cl_d3d" +dnl WINENGINE(-d3d,fted3dqw) + //no d3d on linux +dnl title "CAT(`FTE Engine ',DATE,` - Direct3D')" + desc "The awesome FTE engine (Direct3D-only build)" +TEST()dnl +}')dnl +{ + package "fte_sv" + WINENGINE(-sv,fteqwsv) + LINENGINE2(-sv,fteqw-sv,fteqwsv_lin64.zip) + title "CAT(`FTE Engine ',DATE,` - Server')" + desc "The awesome FTE engine (server-only build)" +TEST()dnl +} +define(`WINPLUG',`category "Plugins" + ver "REVISION" + gamedir "" + license "GPLv2" + { + arch "win_x86" + FILE(fteplug_$1_x86.REVISION.dll) + URL(win32/fteplug_$1_x86.dll) + } + { + arch "win_x64" + FILE(fteplug_$1_x64.REVISION.dll) + URL(win64/fteplug_$1_x64.dll) + }')dnl +define(`LINPLUG',`{ + arch "linux_amd64" + FILE(fteplug_$1_amd64.REVISION,.so) + URL(linux_amd64/fteplug_$1_amd64.so) + }')dnl +GAME(quake, +{ + package "fteplug_ezhud" + WINPLUG(ezhud) + LINPLUG(ezhud) + title "EzHud Plugin" + replace "ezhud" + desc "Some lame alternative configurable hud." +TEST()dnl +})dnl +GAME(quake, +{ + package "fteplug_qi" + WINPLUG(qi) + LINPLUG(qi) + category "Plugins" + title "Quake Injector Plugin" + replace "Quake Injector Plugin" + author "Spike" + website "https://www.quaddicted.com/reviews/" + desc "Provides a way to quickly list+install+load numerous different maps and mods. Some better than others." + desc "If you're a single-player fan then these will keep you going for quite some time." + desc "The database used is from quaddicted.com." +TEST()dnl +})dnl +{ + package "fteplug_irc" + WINPLUG(irc) + LINPLUG(irc) + title "IRC Plugin" + replace "IRC Plugin" + desc "Allows you to converse on IRC servers in-game." +TEST()dnl +} +{ + package "fteplug_xmpp" + WINPLUG(xmpp) + LINPLUG(xmpp) + title "XMPP Plugin" + desc "Allows you to converse on XMPP servers. This also includes a method for NAT holepunching between contacts." +TEST()dnl +} +HIDE(` +{ + package "fteplug_models" + WINPLUG(models) + LINPLUG(models) + title "Model exporter plugin" + desc "" +TEST()dnl +} +{ + package fteplug_ode +TEST()dnl +} +{ + package fteplug_cef +TEST()dnl +} +{ + package "fteplug_ffmpeg" + { + arch "win_x86" + file "fteplug_ffmpeg_x86."#REVISION#".dll" + url "win32/fteplug_ffmpeg_x86.dll" + } + { + arch "win_x64" + file "fteplug_ffmpeg_x64."#REVISION#".dll" + url "win64/fteplug_ffmpeg_x64.dll" + } +// { +// arch "linux_x64" +// file "fteplug_ffmpeg_amd64."#REVISION#".so" +// url "linux_amd64/fteplug_ffmpeg_amd64.so" +// } + ver REVISION + category "Plugins" + title "FFmpeg Plugin" + file "fteplug_ffmpeg" + gamedir "" +TEST()dnl +} +{ + package "libffmpeg" + { + arch "win_x86" + url "win32/ffmpeg-4.0-x86.zip" + } + { + arch "win_x64" + url "win64/ffmpeg-4.0-x64.zip" + } +// { +// arch "linux_x64" +// url "linux_amd64/ffmpeg-4.0-fteplug_ezhud_amd64.so" +// } + ver "4.0" + category "Plugins" + title "FFmpeg Library" + extract "zip" + gamedir "" +} +')dnl +GAME(quake2, +{ + package "q2game_baseq2" + { + arch "win_x86" + FILE(q2gamex86_baseq2.dll) + URL(win32/q2gamex86_baseq2.dll) + } + { + arch "win_x64" + FILE(q2gamex64_baseq2.dll) + URL(win64/q2gamex64_baseq2.dll) + } + { + arch "linux_amd64" + FILE(q2gameamd64_baseq2.so) + URL(linux_amd64/q2gameamd64_baseq2.so) + } + ver "20190606" + category "Mods" + title "Gamecode: Base Game" + license "GPLv2" + website "https://github.com/yquake2/yquake2" + desc "Quake2 Gamecode (from yamagiq2). Required for single player or servers." +TEST()dnl +})dnl +GAME(quake, +{ + package "fte_csaddon" + category "Plugins" + title "Ingame Map Editor" + ver REVISION + gamedir "fte" + FILE(csaddon.dat) + URL(csaddon/csaddon.dat) + desc "This is Spike's map editing user interface. It is only active while running singleplayer (or sv_cheats is enabled)." + desc "To activate, set the ca_show cvar to 1 (suggestion: ^abind c toggle ca_show^a)." + license "GPLv2, source on fte's svn" + author "Spike" +TEST()dnl +})dnl +GAME(quake, +{ + package "fte_menusys" + category "AfterQuake" + title "Replacement Menus" + ver REVISION + gamedir "fte" + FILE(menu.dat) + URL(csaddon/menu.dat) + desc "This provides a more modern mouse-first menu system." + license "GPLv2, source on fte's svn" + author "Spike" +TEST()dnl +})dnl + diff --git a/quakec/dpsymbols.src b/quakec/dpsymbols.src new file mode 100644 index 000000000..1cc4d2242 --- /dev/null +++ b/quakec/dpsymbols.src @@ -0,0 +1,108 @@ +//NOTE: This file exists purely for generation of the genericdefs/*_api.qc files distributed in ftetools.zip. +//It is consumed by FTE's build scripts and exists to normalize DP's misnamed defs to match FTE's, and some other fixups/omissions with DP defs. +//Patches welcome... + +#pragma noref 1 + +#ifdef TEST +#include "fteextensions.qc" +#endif + +//attempt to normalize things. +#define ReadAngle readangle +#define ReadByte readbyte +#define ReadChar readchar +#define ReadCoord readcoord +#define ReadFloat readfloat +#define ReadLong readlong +#define ReadShort readshort +#define ReadString readstring +#define draw_getimagesize drawgetimagesize + +#define skel_mul_bone skel_premul_bone +#define skel_mul_bones skel_premul_bones + +#define setsensitivityscale setsensitivityscaler +#define centerprint cprint +#define cs_project project +#define cs_unproject unproject +#define ChangeYaw changeyaw + +#define entitybyindex edict_num +#define adddynamiclight2 dynamiclight_add + +#define FIELD_ENTITY EV_ENTITY +#define FIELD_FLOAT EV_FLOAT +#define FIELD_FUNCTION EV_FUNCTION +#define FIELD_STRING EV_STRING +#define FIELD_VECTOR EV_VECTOR +#define STAT_MONSTERS STAT_KILLEDMONSTERS +#define STAT_SECRETS STAT_FOUNDSECRETS +#define STAT_WEAPONMODEL STAT_WEAPONMODELI + +#define E_ABSMAX GE_ABSMAX +#define E_ABSMIN GE_ABSMIN +#define E_ACTIVE GE_ACTIVE +#define E_ALPHA GE_ALPHA +#define E_COLORMOD GE_COLORMOD +#define E_FORWARD GE_FORWARD +#define E_MAXS GE_MAXS +#define E_MINS GE_MINS +#define E_ORIGIN GE_ORIGIN +#define E_ORIGINANDVECTORS GE_ORIGINANDVECTORS +#define E_PANTSCOLOR GE_PANTSCOLOR +#define E_RIGHT GE_RIGHT +#define E_SCALE GE_SCALE +#define E_SHIRTCOLOR GE_SHIRTCOLOR +#define E_SKIN GE_SKIN +#define E_UP GE_UP + +#define VF_FOV_X VF_FOVX +#define VF_FOV_Y VF_FOVX + + +#define PI M_PI +#define MASK_NORMAL MASK_ENGINE +#define MASK_ENGINEVIEWMODELS MASK_VIEWMODEL +#define false FALSE +#define true TRUE + + + + +#ifdef SSQC + #include "dpdefs/progsdefs.qc" + #include "dpdefs/dpextensions.qc" + + .float SendFlags; + .float gravity; + float MSG_ENTITY=5; +#endif +#ifdef CSQC + #define drawstring drawrawstring + #include "dpdefs/csprogsdefs.qc" + #undef drawstring + vector(vector position, string text, vector scale, vector rgb, float alpha, float flag) drawstring = #326; + + //not actually defined for some fucked up reason, but work none the less. These are the ones that I use - there'll be others. + const float IE_KEYDOWN = 0; + const float IE_KEYUP = 1; +#endif +#ifdef MENU + #define cmd localcmd + #include "dpdefs/menudefs.qc" + const float GGDI_GAMEDIR = GETGAMEDIRINFO_NAME; + const float GGDI_DESCRIPTION = GETGAMEDIRINFO_DESCRIPTION; + + //not actually defined for some fucked up reason, but work none the less. These are the ones that I use - there'll be others. + float(float s) asin = #471; + float(float c) acos = #472; + float(float t) atan = #473; + float(float c, float s) atan2 = #474; + float(float a) tan = #475; + string(string filename) whichpack = #503; +#endif + + +float(__variant) checkbuiltin = #0; //not really present in DP, but #0 is technically just an OP_DONE so returns 0 so its actually okay in the end. its important for this to not generate extra warnings. +