diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 404e8d353..e00f9c966 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -2001,8 +2001,13 @@ void CL_SendCmd (double frametime, qboolean mainloop) #endif #ifdef Q3CLIENT case CP_QUAKE3: + msecs -= (double)msecstouse; CLQ3_SendCmd(&independantphysics[0]); memset(&independantphysics[0], 0, sizeof(independantphysics[0])); + + //don't bank too much, because that results in banking speedcheats + if (msecs > 200) + msecs = 200; return; // Q3 does it's own thing #endif default: diff --git a/engine/client/image.c b/engine/client/image.c index 31ec51be3..ae1248720 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -3547,13 +3547,46 @@ static void Image_8_BGR_RGB_Swap(qbyte *data, unsigned int w, unsigned int h) } } -static void Image_ChangeFormat(struct pendingtextureinfo *mips, uploadfmt_t origfmt) +static void Image_ChangeFormat(struct pendingtextureinfo *mips, unsigned int flags, uploadfmt_t origfmt) { int mip; if (mips->type != PTI_2D) return; //blurgh + if (flags & IF_PALETTIZE) + { + if (mips->encoding == PTI_RGBX8) + { + mips->encoding = PTI_R8; + for (mip = 0; mip < mips->mipcount; mip++) + { + unsigned int i; + unsigned char *out; + unsigned char *in; + void *needfree = NULL; + + in = mips->mip[mip].data; + if (mips->mip[mip].needfree) + out = in; + else + { + needfree = in; + out = BZ_Malloc(mips->mip[mip].width*mips->mip[mip].height*sizeof(*out)); + mips->mip[mip].data = out; + } + mips->mip[mip].datasize = mips->mip[mip].width*mips->mip[mip].height; + mips->mip[mip].needfree = true; + + for (i = 0; i < mips->mip[mip].width*mips->mip[mip].height; i++, in+=4) + out[i] = GetPaletteIndex(in[0], in[1], in[2]); + + if (needfree) + BZ_Free(needfree); + } + } + } + //if that format isn't supported/desired, try converting it. if (sh_config.texfmt[mips->encoding]) return; @@ -3721,7 +3754,7 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag //8bit opaque data Image_RoundDimensions(&mips->mip[0].width, &mips->mip[0].height, flags); flags |= IF_NOPICMIP; - if (!r_dodgymiptex.ival && mips->mip[0].width == imgwidth && mips->mip[0].height == imgheight) + if (/*!r_dodgymiptex.ival &&*/ mips->mip[0].width == imgwidth && mips->mip[0].height == imgheight) { unsigned int pixels = (imgwidth>>0) * (imgheight>>0) + @@ -4153,7 +4186,7 @@ static qboolean Image_LoadRawTexture(texid_t tex, unsigned int flags, void *rawd return false; } Image_GenerateMips(mips, flags); - Image_ChangeFormat(mips, fmt); + Image_ChangeFormat(mips, flags, fmt); tex->width = imgwidth; tex->height = imgheight; @@ -4612,7 +4645,7 @@ image_t *Image_FindTexture(const char *identifier, const char *subdir, unsigned tex = Hash_Get(&imagetable, identifier); while(tex) { - if (!((tex->flags ^ flags) & IF_CLAMP)) + if (!((tex->flags ^ flags) & (IF_CLAMP|IF_PALETTIZE))) { #ifdef PURGEIMAGES if (!strcmp(subdir, tex->subpath?tex->subpath:"")) @@ -4847,7 +4880,7 @@ void Image_Upload (texid_t tex, uploadfmt_t fmt, void *data, void *palette, in if (!Image_GenMip0(&mips, flags, data, palette, width, height, fmt, false)) return; Image_GenerateMips(&mips, flags); - Image_ChangeFormat(&mips, fmt); + Image_ChangeFormat(&mips, flags, fmt); rf->IMG_LoadTextureMips(tex, &mips); tex->width = width; tex->height = height; diff --git a/engine/client/m_download.c b/engine/client/m_download.c index a70c6939e..48c94f788 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -48,7 +48,7 @@ vfsfile_t *FS_GZ_DecompressWriteFilter(vfsfile_t *outfile, qboolean autoclosefil #ifndef SVNREVISION #define SVNREVISION - #endif -#define DOWNLOADABLESARGS "?ver=" STRINGIFY(SVNREVISION) PHPVK PHPGL PHPD3D PHPMIN PHPLEG PHPDBG "&arch="PLATFORM "_" ARCH_CPU_POSTFIX +#define DOWNLOADABLESARGS "ver=" STRINGIFY(SVNREVISION) PHPVK PHPGL PHPD3D PHPMIN PHPLEG PHPDBG "&arch="PLATFORM "_" ARCH_CPU_POSTFIX @@ -81,6 +81,7 @@ extern cvar_t fs_downloads_url; #define DPF_HIDDEN 0x80 //wrong arch, file conflicts, etc. still listed if actually installed. #define DPF_ENGINE 0x100 //engine update. replaces old autoupdate mechanism #define DPF_PURGE 0x200 //package should be completely removed (ie: the dlcache dir too). if its still marked then it should be reinstalled anew. available on cached or corrupt packages, implied by native. +#define DPF_MANIFEST 0x400 //package was named by the manifest, and should only be uninstalled after a warning. //pak.lst //priories <0 @@ -172,8 +173,10 @@ typedef struct package_s { static qboolean loadedinstalled; static package_t *availablepackages; static int numpackages; +static char *manifestpackage; //metapackage named by the manicfest. +static qboolean domanifestinstall; -qboolean doautoupdate; //updates will be marked (but not applied without the user's actions) +static qboolean doautoupdate; //updates will be marked (but not applied without the user's actions) //FIXME: these are allocated for the life of the exe. changing basedir should purge the list. static int numdownloadablelists = 0; @@ -185,7 +188,7 @@ static struct qboolean save; //written into our local file struct dl_download *curdl; //the download context } downloadablelist[32]; -int downloadablessequence; //bumped any time any package is purged +static int downloadablessequence; //bumped any time any package is purged static void PM_FreePackage(package_t *p) { @@ -222,6 +225,9 @@ static void PM_FreePackage(package_t *p) for (i = 0; i < countof(p->mirror); i++) Z_Free(p->mirror[i]); + Z_Free(p->name); + Z_Free(p->category); + Z_Free(p->title); Z_Free(p->description); Z_Free(p->author); Z_Free(p->license); @@ -665,6 +671,7 @@ static void PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, c char *arch = NULL; char *qhash = NULL; char *title = NULL; + char *category = NULL; char *description = NULL; char *license = NULL; char *author = NULL; @@ -683,8 +690,10 @@ static void PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, c char *arg = Cmd_Argv(i); if (!strncmp(arg, "url=", 4)) url = arg+4; - else if (!strncmp(arg, "title=", 8)) - title = arg+8; + else if (!strncmp(arg, "category=", 9)) + category = arg+9; + else if (!strncmp(arg, "title=", 6)) + title = arg+6; else if (!strncmp(arg, "gamedir=", 8)) gamedir = arg+8; else if (!strncmp(arg, "ver=", 4)) @@ -740,13 +749,31 @@ static void PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, c } } - if (*prefix) - Q_snprintfz(pathname, sizeof(pathname), "%s/%s", prefix, fullname); + if (category) + { + p->name = Z_StrDup(fullname); + + if (*prefix) + Q_snprintfz(pathname, sizeof(pathname), "%s/%s", prefix, category); + else + Q_snprintfz(pathname, sizeof(pathname), "%s", category); + if (*pathname) + { + if (pathname[strlen(pathname)-1] != '/') + Q_strncatz(pathname, "/", sizeof(pathname)); + } + p->category = Z_StrDup(pathname); + } else - Q_snprintfz(pathname, sizeof(pathname), "%s", fullname); - p->name = Z_StrDup(COM_SkipPath(pathname)); - *COM_SkipPath(pathname) = 0; - p->category = Z_StrDup(pathname); + { + if (*prefix) + Q_snprintfz(pathname, sizeof(pathname), "%s/%s", prefix, fullname); + else + Q_snprintfz(pathname, sizeof(pathname), "%s", fullname); + p->name = Z_StrDup(COM_SkipPath(pathname)); + *COM_SkipPath(pathname) = 0; + p->category = Z_StrDup(pathname); + } if (!title) title = p->name; @@ -1219,6 +1246,7 @@ static void PM_PrintChanges(void) Con_Printf("<%i package(s) changed>\n", changes); } +static void PM_ApplyChanges(void); static void PM_ListDownloaded(struct dl_download *dl) { @@ -1246,16 +1274,46 @@ static void PM_ListDownloaded(struct dl_download *dl) else downloadablelist[i].received = -1; - if (!doautoupdate) + if (!doautoupdate && !domanifestinstall) return; //don't spam this. for (i = 0; i < numdownloadablelists; i++) { if (!downloadablelist[i].received) break; } - if (i == numdownloadablelists) + if (domanifestinstall) + { + package_t *meta; + meta = PM_MarkedPackage(manifestpackage); + if (!meta) + meta = PM_FindPackage(manifestpackage); + if (meta) + { + PM_RevertChanges(); + PM_MarkPackage(meta); + PM_ApplyChanges(); + +#ifdef DOWNLOADMENU + if (!isDedicated) + { + if (Key_Dest_Has(kdm_emenu)) + { + Key_Dest_Remove(kdm_emenu); + m_state = m_none; + } +#ifdef MENU_DAT + if (Key_Dest_Has(kdm_gmenu)) + MP_Toggle(0); +#endif + Cmd_ExecuteString("menu_download\n", RESTRICT_LOCAL); + + } +#endif + return; + } + } + if (doautoupdate && i == numdownloadablelists) { - doautoupdate = true; if (PM_MarkUpdates()) { #ifdef DOWNLOADMENU @@ -1282,6 +1340,7 @@ static void PM_ListDownloaded(struct dl_download *dl) static void PM_UpdatePackageList(qboolean autoupdate, int retry) { unsigned int i; + int setting; if (retry>1 || fs_downloads_url.modified) PM_Shutdown(); @@ -1303,7 +1362,11 @@ static void PM_UpdatePackageList(qboolean autoupdate, int retry) if (downloadablelist[i].curdl) continue; - downloadablelist[i].curdl = HTTP_CL_Get(va("%s"DOWNLOADABLESARGS, downloadablelist[i].url), NULL, PM_ListDownloaded); + setting = Sys_GetAutoUpdateSetting(); +// if (setting == UPD_UNSUPPORTED) +// setting = autoupdatesetting+1; + + downloadablelist[i].curdl = HTTP_CL_Get(va("%s%s"DOWNLOADABLESARGS"%s", downloadablelist[i].url, strchr(downloadablelist[i].url,'?')?"&":"?", (setting>=UPD_TESTING)?"test=1":""), NULL, PM_ListDownloaded); if (downloadablelist[i].curdl) { downloadablelist[i].curdl->user_num = i; @@ -1441,7 +1504,7 @@ static void PM_WriteInstalledPackages(void) if (p->description) { Q_strncatz(buf, " ", sizeof(buf)); - COM_QuotedConcat(va("description=%s", p->description), buf, sizeof(buf)); + COM_QuotedConcat(va("desc=%s", p->description), buf, sizeof(buf)); } if (p->license) { @@ -1735,23 +1798,60 @@ static char *PM_GetTempName(package_t *p) return Z_StrDup(destname); } +static void PM_AddDownloadedPackage(const char *filename) +{ + char pathname[1024]; + package_t *p; + Q_snprintfz(pathname, sizeof(pathname), "%s/%s", "Cached", filename); + p->name = Z_StrDup(COM_SkipPath(pathname)); + *COM_SkipPath(pathname) = 0; + p->category = Z_StrDup(pathname); + + Q_strncpyz(p->version, "", sizeof(p->version)); + + Q_snprintfz(p->gamedir, sizeof(p->gamedir), "%s", ""); + p->fsroot = FS_ROOT; + p->extract = EXTRACT_COPY; + p->priority = 0; + p->flags = DPF_INSTALLED; + + p->title = Z_StrDup(p->name); + p->arch = NULL; + p->qhash = NULL; //FIXME + p->description = NULL; + p->license = NULL; + p->author = NULL; + p->previewimage = NULL; +} + +int PM_IsApplying(void) +{ + package_t *p; + int count = 0; + int i; + for (p = availablepackages; p ; p=p->next) + { + if (p->download) + count++; + } + for (i = 0; i < numdownloadablelists; i++) + { + if (downloadablelist[i].curdl) + count++; + } + return count; +} + //looks for the next package that needs downloading, and grabs it static void PM_StartADownload(void) { vfsfile_t *tmpfile; char *temp; -// char native[MAX_OSPATH]; package_t *p; - int simultaneous = 1; + const int simultaneous = 1; int i; - for (p = availablepackages; p ; p=p->next) - { - if (p->download) - simultaneous--; - } - - for (p = availablepackages; p && simultaneous > 0; p=p->next) + for (p = availablepackages; p && simultaneous > PM_IsApplying(); p=p->next) { if (p->trymirrors) { //flagged for a (re?)download @@ -1848,8 +1948,6 @@ static void PM_StartADownload(void) VFS_CLOSE(tmpfile); FS_Remove(temp, p->fsroot); } - - simultaneous--; } } } @@ -1862,7 +1960,9 @@ static void PM_ApplyChanges(void) for (link = &availablepackages; *link ; ) { p = *link; - if ((p->flags & DPF_PURGE) || (!(p->flags&DPF_MARKED) && (p->flags&DPF_INSTALLED))) + if (p->download) + ; //erk, dude, don't do two! + else if ((p->flags & DPF_PURGE) || (!(p->flags&DPF_MARKED) && (p->flags&DPF_INSTALLED))) { //if we don't want it but we have it anyway: qboolean reloadpacks = false; struct packagedep_s *dep; @@ -1941,6 +2041,20 @@ static void PM_ApplyChanges(void) PM_StartADownload(); //and try to do those downloads. } +void PM_ManifestPackage(const char *metaname, qboolean mark) +{ + domanifestinstall = mark; + Z_Free(manifestpackage); + if (metaname) + { + manifestpackage = Z_StrDup(metaname); + if (mark) + PM_UpdatePackageList(false, false); + } + else + manifestpackage = NULL; +} + void PM_Command_f(void) { package_t *p; @@ -1990,7 +2104,7 @@ void PM_Command_f(void) else status = ""; - Con_Printf(" ^[%s%s%s%s^] %s %s\n", markup, p->name, p->arch?":":"", p->arch?p->arch:"", status, strcmp(p->name, p->title)?p->title:""); + Con_Printf(" ^[%s%s%s%s^] %s^9 %s\n", markup, p->name, p->arch?":":"", p->arch?p->arch:"", status, strcmp(p->name, p->title)?p->title:""); } Con_Printf("\n"); } @@ -2252,7 +2366,7 @@ static void MD_Draw (int x, int y, struct menucustom_s *c, struct menu_s *m) } } - n = p->name; + n = p->title; if (p->flags & DPF_DISPLAYVERSION) n = va("%s (%s)", n, *p->version?p->version:"unversioned"); @@ -2361,10 +2475,10 @@ static void MD_AutoUpdate_Draw (int x, int y, struct menucustom_s *c, struct men char *settings[] = { "Unsupported", - "Revert", + "Revert Engine", "Off", "Stable Updates", - "Unsable Updates" + "Test Updates" }; char *text; int setting = Sys_GetAutoUpdateSetting(); diff --git a/engine/client/merged.h b/engine/client/merged.h index 51a974550..126b58f2b 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -158,6 +158,9 @@ enum mlverbosity_e MLV_ERROR }; +const char *Mod_GetEntitiesString(struct model_s *mod); +void Mod_SetEntitiesStringLen(struct model_s *mod, const char *str, size_t strsize); +void Mod_SetEntitiesString(struct model_s *mod, const char *str, qboolean docopy); extern void Mod_ClearAll (void); extern void Mod_Purge (enum mod_purge_e type); extern struct model_s *Mod_FindName (const char *name); //find without loading. needload should be set. @@ -166,7 +169,7 @@ extern struct model_s *Mod_LoadModel (struct model_s *mod, enum mlverbosity_e extern void *Mod_Extradata (struct model_s *mod); // handles caching extern void Mod_TouchModel (const char *name); extern const char *Mod_FixName (const char *modname, const char *worldname); //remaps the name appropriately -char *Mod_ParseWorldspawnKey (const char *ents, const char *key, char *buffer, size_t sizeofbuffer); +const char *Mod_ParseWorldspawnKey (struct model_s *mod, const char *key, char *buffer, size_t sizeofbuffer); extern void Mod_Think (void); extern int Mod_SkinNumForName (struct model_s *model, int surfaceidx, const char *name); diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index d2cdfc8ee..e2c857116 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -3246,7 +3246,7 @@ static void QCBUILTIN PF_cs_getentitytoken (pubprogfuncs_t *prinst, struct globa { const char *s = PR_GetStringOfs(prinst, OFS_PARM0); if (*s == 0) - s = cl.worldmodel?cl.worldmodel->entities:NULL; + s = Mod_GetEntitiesString(cl.worldmodel); csqcmapentitydata = s; G_INT(OFS_RETURN) = 0; return; @@ -6939,14 +6939,14 @@ void CSQC_WorldLoaded(void) CSQC_FindGlobals(false); csqcmapentitydataloaded = true; - csqcmapentitydata = cl.worldmodel?cl.worldmodel->entities:NULL; + csqcmapentitydata = Mod_GetEntitiesString(cl.worldmodel); csqc_world.worldmodel = cl.worldmodel; World_RBE_Start(&csqc_world); worldent = (csqcedict_t *)EDICT_NUM(csqcprogs, 0); worldent->v->solid = SOLID_BSP; - wmodelindex = CS_FindModel(cl.worldmodel->name, &tmp); + wmodelindex = CS_FindModel(cl.worldmodel?cl.worldmodel->name:"", &tmp); tmp = csqc_worldchanged; csqc_setmodel(csqcprogs, worldent, wmodelindex); csqc_worldchanged = tmp; diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index ca493090b..41425a86a 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -1597,6 +1597,7 @@ texid_t R2D_RT_Configure(const char *id, int width, int height, uploadfmt_t rtfm if (rtfmt) { + tid->flags = (tid->flags & ~(IF_NEAREST|IF_LINEAR)) | (imageflags & (IF_NEAREST|IF_LINEAR)); Image_Upload(tid, rtfmt, NULL, NULL, width, height, imageflags); tid->width = width; tid->height = height; diff --git a/engine/client/r_d3.c b/engine/client/r_d3.c index ade0704d0..b16ec8f24 100644 --- a/engine/client/r_d3.c +++ b/engine/client/r_d3.c @@ -1429,7 +1429,7 @@ qboolean QDECL D3_LoadMap_CollisionMap(model_t *mod, void *buf, size_t bufsize) /*load up the .map so we can get some entities (anyone going to bother making a qc mod compatible with this?)*/ COM_StripExtension(mod->name, token, sizeof(token)); - mod->entities = FS_LoadMallocFile(va("%s.map", token), NULL); + Mod_SetEntitiesString(mod, FS_LoadMallocFile(va("%s.map", token), NULL), true); mod->funcs.FindTouchedLeafs = D3_FindTouchedLeafs; mod->funcs.NativeTrace = D3_Trace; diff --git a/engine/client/render.h b/engine/client/render.h index 78274c304..dcda32866 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -403,6 +403,7 @@ enum imageflags IF_MIPCAP = 1<<10, IF_PREMULTIPLYALPHA = 1<<12, //rgb *= alpha + IF_PALETTIZE = 1<<21, IF_NOPURGE = 1<<22, IF_HIGHPRIORITY = 1<<23, IF_LOWPRIORITY = 1<<24, @@ -506,7 +507,7 @@ struct llightinfo_s; void LightFace (struct relight_ctx_s *ctx, struct llightinfo_s *threadctx, int surfnum); //version that is aware of bsp trees void LightPlane (struct relight_ctx_s *ctx, struct llightinfo_s *threadctx, qbyte surf_styles[4], 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); //special version that doesn't know what a face is or anything. struct relight_ctx_s *LightStartup(struct relight_ctx_s *ctx, struct model_s *model, qboolean shadows); -void LightReloadEntities(struct relight_ctx_s *ctx, char *entstring, qboolean ignorestyles); +void LightReloadEntities(struct relight_ctx_s *ctx, const char *entstring, qboolean ignorestyles); void LightShutdown(struct relight_ctx_s *ctx, struct model_s *mod); extern const size_t lightthreadctxsize; #endif diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 69d624473..90d7f70f9 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -1222,7 +1222,7 @@ qboolean R_ApplyRenderer (rendererstate_t *newr) { if (newr->renderer->rtype == qrenderer && currentrendererstate.renderer) { - R_SetRenderer(newr->renderer); + R_SetRenderer(newr->renderer); return true; //no point } diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 84491463d..9753e5609 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -3546,7 +3546,7 @@ qboolean Sys_DoInstall(void) int pct = -100; char fname[MAX_OSPATH]; memset(&wc, 0, sizeof(wc)); - wc.style = 0; + wc.style = 0; wc.lpfnWndProc = NoCloseWindowProc;//Progress_Wnd; wc.hInstance = hInstance; wc.hCursor = LoadCursor (NULL,IDC_ARROW); @@ -3613,7 +3613,7 @@ qboolean Sys_DoInstall(void) } /*create startmenu icon*/ - if (MessageBoxU(NULL, va("Create Startmenu icon for %s?", fs_gamename.string), fs_gamename.string, MB_YESNO|MB_ICONQUESTION|MB_TOPMOST) == IDYES) + if (MessageBoxU(NULL, va("Create start-menu icon for %s?", fs_gamename.string), fs_gamename.string, MB_YESNO|MB_ICONQUESTION|MB_TOPMOST) == IDYES) { HRESULT hres; IShellLinkW *psl; diff --git a/engine/client/wad.c b/engine/client/wad.c index 0e05a97f9..716d44bef 100644 --- a/engine/client/wad.c +++ b/engine/client/wad.c @@ -42,6 +42,9 @@ void W_CleanupName (const char *in, char *out) { int i; int c; + + if (!strncmp(in, "textures/", 9)) + in += 9; for (i=0 ; i<16 ; i++ ) { @@ -694,7 +697,7 @@ void Mod_ParseInfoFromEntityLump(model_t *wmodel) //actually, this should be in { char token[4096]; char key[128]; - char *data = wmodel->entities; + const char *data = Mod_GetEntitiesString(wmodel); mapskys_t *msky; cl.skyrotate = 0; @@ -730,7 +733,7 @@ void Mod_ParseInfoFromEntityLump(model_t *wmodel) //actually, this should be in break; // error if (!strcmp("wad", key)) // for HalfLife maps { - if (wmodel->fromgame == fg_halflife || wmodel->type == mod_heightmap) + if (1) { Q_strncatz(wads, ";", sizeof(wads)); //cache it for later (so that we don't play with any temp memory yet) Q_strncatz(wads, token, sizeof(wads)); //cache it for later (so that we don't play with any temp memory yet) @@ -834,8 +837,8 @@ qboolean Wad_NextDownload (void) { char wadname[4096+9]="textures/"; int i, j, k; - - if (*wads) //now go about checking the wads + model_t *wmodel = cl.worldmodel; + if (wmodel && (wmodel->fromgame == fg_halflife || wmodel->type == mod_heightmap) && *wads) //now go about checking the wads { j = 0; wads[4095] = '\0'; diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 09c365031..df2538ebc 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -3155,22 +3155,7 @@ static void *Q1MDL_LoadSkins_GL (galiasinfo_t *galias, dmdl_t *pq1inmodel, model galiasskin_t *outskin = galias->ofsskins; const char *slash; unsigned int texflags; - const char *defaultshader; - - if (r_softwarebanding && qrenderer == QR_OPENGL && sh_config.progs_supported) - { - defaultshader = - "{\n" - "program defaultskin#EIGHTBIT\n" - "affine\n" - "{\n" - "map $colourmap\n" - "}\n" - "}\n" - ; - } - else - defaultshader = NULL; + const char *defaultshader = NULL; s = pq1inmodel->skinwidth*pq1inmodel->skinheight; for (i = 0; i < pq1inmodel->numskins; i++) diff --git a/engine/common/common.c b/engine/common/common.c index 285ba1bf9..ba29d8dac 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -108,7 +108,7 @@ cvar_t gameversion = CVARFD("gameversion","", CVAR_SERVERINFO, "gamecode version cvar_t gameversion_min = CVARD("gameversion_min","", "gamecode version for server browsers"); cvar_t gameversion_max = CVARD("gameversion_max","", "gamecode version for server browsers"); cvar_t fs_gamename = CVARAFD("com_fullgamename", NULL, "fs_gamename", CVAR_NOSET, "The filesystem is trying to run this game"); -cvar_t fs_downloads_url = CVARFD("fs_downloads_url", NULL, CVAR_NOSET, "The URL of a package updates list."); +cvar_t fs_downloads_url = CVARFD("fs_downloads_url", NULL, CVAR_NOTFROMSERVER|CVAR_NOSAVE|CVAR_NOSET, "The URL of a package updates list."); cvar_t com_protocolname = CVARAD("com_protocolname", NULL, "com_gamename", "The protocol game name used for dpmaster queries. For compatibility with DP, you can set this to 'DarkPlaces-Quake' in order to be listed in DP's master server, and to list DP servers."); cvar_t com_parseutf8 = CVARD("com_parseutf8", "1", "Interpret console messages/playernames/etc as UTF-8. Requires special fonts. -1=iso 8859-1. 0=quakeascii(chat uses high chars). 1=utf8, revert to ascii on decode errors. 2=utf8 ignoring errors"); //1 parse. 2 parse, but stop parsing that string if a char was malformed. cvar_t com_parseezquake = CVARD("com_parseezquake", "0", "Treat chevron chars from configs as a per-character flag. You should use this only for compat with nquake's configs."); @@ -2715,17 +2715,18 @@ consolecolours_t consolecolours[MAXCONCOLOURS] = { }; // This is for remapping the Q3 color codes to character masks, including ^9 +// if using this table, make sure the truecolour flag is disabled first. conchar_t q3codemasks[MAXQ3COLOURS] = { - 0x00000000, // 0, black - 0x0c000000, // 1, red - 0x0a000000, // 2, green - 0x0e000000, // 3, yellow - 0x09000000, // 4, blue - 0x0b000000, // 5, cyan - 0x0d000000, // 6, magenta - 0x0f000000, // 7, white - 0x0f100000, // 8, half-alpha white (BX_COLOREDTEXT) - 0x07000000 // 9, "half-intensity" (BX_COLOREDTEXT) + COLOR_BLACK << CON_FGSHIFT, // 0, black + COLOR_RED << CON_FGSHIFT, // 1, red + COLOR_GREEN << CON_FGSHIFT, // 2, green + COLOR_YELLOW << CON_FGSHIFT, // 3, yellow + COLOR_BLUE << CON_FGSHIFT, // 4, blue + COLOR_CYAN << CON_FGSHIFT, // 5, cyan + COLOR_MAGENTA << CON_FGSHIFT, // 6, magenta + COLOR_WHITE << CON_FGSHIFT, // 7, white + (COLOR_WHITE << CON_FGSHIFT)|CON_HALFALPHA, // 8, half-alpha white (BX_COLOREDTEXT) + COLOR_GREY << CON_FGSHIFT // 9, "half-intensity" (BX_COLOREDTEXT) }; //Converts a conchar_t string into a char string. returns the null terminator. pass NULL for stop to calc it @@ -3203,7 +3204,7 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t { //q3 colour codes if (ext & CON_RICHFORECOLOUR) ext = (COLOR_WHITE << CON_FGSHIFT) | (ext&~(CON_RICHFOREMASK|CON_RICHFORECOLOUR)); - ext = q3codemasks[str[1]-'0'] | (ext&~CON_Q3MASK); //change colour only. + ext = q3codemasks[str[1]-'0'] | (ext&~(CON_WHITEMASK|CON_HALFALPHA)); //change colour only. } else if (str[1] == '&') // extended code { diff --git a/engine/common/console.h b/engine/common/console.h index 014fb6c43..95a7638f8 100644 --- a/engine/common/console.h +++ b/engine/common/console.h @@ -55,7 +55,6 @@ extern conchar_t q3codemasks[MAXQ3COLOURS]; #define CON_RICHGSHIFT 24 #define CON_RICHRSHIFT 28 //high nibble -#define CON_Q3MASK 0x0F100000 #define CON_WHITEMASK 0x0F000000 // must be constant. things assume this #define CON_DEFAULTCHAR (CON_WHITEMASK | 32) diff --git a/engine/common/fs.c b/engine/common/fs.c index cdfc78666..353fac2c4 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -3948,6 +3948,7 @@ void FS_Shutdown(void) if (!fs_thread_mutex) return; + PM_ManifestPackage(NULL, false); FS_FreePaths(); Sys_DestroyMutex(fs_thread_mutex); fs_thread_mutex = NULL; @@ -4185,6 +4186,8 @@ static char fspdl_finalpath[MAX_OSPATH]; static void FS_BeginNextPackageDownload(void); qboolean FS_DownloadingPackage(void) { + if (PM_IsApplying()) + return true; return !fs_manifest || !!curpackagedownload; } //vfsfile_t *FS_DecompressXZip(vfsfile_t *infile, vfsfile_t *outfile); @@ -4370,6 +4373,8 @@ static void FS_PackageDownloaded(struct dl_download *dl) { Con_Printf("Unable to rename \"%s\" to \"%s\"\n", fspdl_temppath, fspdl_finalpath); } +// else +// PM_AddDownloadedPackage(fspdl_finalpath); } } Sys_remove (fspdl_temppath); @@ -4715,6 +4720,7 @@ static void FS_ManifestUpdated(struct dl_download *dl) void FS_BeginManifestUpdates(void) { ftemanifest_t *man = fs_manifest; + PM_ManifestPackage(man->installupd, man->doinstall); if (curpackagedownload || !man) return; @@ -4914,6 +4920,8 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean if (fs_manifest && fs_manifest->downloadsurl) olddownloadsurl = Z_StrDup(fs_manifest->downloadsurl); + else if (!fs_manifest && man->downloadsurl) + olddownloadsurl = Z_StrDup(man->downloadsurl); else olddownloadsurl = NULL; @@ -4935,7 +4943,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean } fs_manifest = man; - if (!man->doinstall) + if (!man->doinstall && strcmp(man->downloadsurl?man->downloadsurl:"", olddownloadsurl?olddownloadsurl:"")) { //make sure we only fuck over the user if this is a 'secure' manifest, and not hacked in some way. Z_Free(man->downloadsurl); man->downloadsurl = olddownloadsurl; @@ -5167,6 +5175,7 @@ void FS_CreateBasedir(const char *path) com_installer = false; Q_strncpyz (com_gamepath, path, sizeof(com_gamepath)); COM_CreatePath(com_gamepath); + fs_manifest->doinstall = true; FS_ChangeGame(fs_manifest, true, false); if (host_parms.manifest) diff --git a/engine/common/fs.h b/engine/common/fs.h index f25eaa66e..8430203a6 100644 --- a/engine/common/fs.h +++ b/engine/common/fs.h @@ -68,6 +68,8 @@ void FS_UnRegisterFileSystemModule(void *module); void FS_AddHashedPackage(searchpath_t **oldpaths, const char *parent_pure, const char *parent_logical, searchpath_t *search, unsigned int loadstuff, const char *pakpath, const char *qhash, const char *pakprefix); void PM_LoadPackages(searchpath_t **oldpaths, const char *parent_pure, const char *parent_logical, searchpath_t *search, unsigned int loadstuff, int minpri, int maxpri); +int PM_IsApplying(void); +void PM_ManifestPackage(const char *name, qboolean doinstall); void Menu_Download_Update(void); int FS_EnumerateKnownGames(qboolean (*callback)(void *usr, ftemanifest_t *man), void *usr); diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 0642b4b5b..aa28132fd 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -56,6 +56,7 @@ qboolean Mod_LoadVertexNormals (model_t *loadmodel, qbyte *mod_base, lump_t *l); qboolean Mod_LoadEdges (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean lm); qboolean Mod_LoadMarksurfaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean lm); qboolean Mod_LoadSurfedges (model_t *loadmodel, qbyte *mod_base, lump_t *l); +void Mod_LoadEntities (model_t *loadmodel, qbyte *mod_base, lump_t *l); extern void BuildLightMapGammaTable (float g, float c); @@ -1497,7 +1498,7 @@ qboolean CModQ2_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l, qboolean li unsigned short lmshift, lmscale; char buf[64]; - lmscale = atoi(Mod_ParseWorldspawnKey(mod->entities, "lightmap_scale", buf, sizeof(buf))); + lmscale = atoi(Mod_ParseWorldspawnKey(mod, "lightmap_scale", buf, sizeof(buf))); if (!lmscale) lmshift = LMSHIFT_DEFAULT; else @@ -2036,20 +2037,6 @@ qboolean CModQ2_LoadVisibility (model_t *mod, qbyte *mod_base, lump_t *l) return true; } -/* -================= -CMod_LoadEntityString -================= -*/ -void CMod_LoadEntityString (model_t *mod, qbyte *mod_base, lump_t *l) -{ -// if (l->filelen > MAX_Q2MAP_ENTSTRING) -// Host_Error ("Map has too large entity lump"); - - mod->entities = Z_Malloc(l->filelen+1); - memcpy (mod->entities, mod_base + l->fileofs, l->filelen); -} - #ifdef Q3BSPS qboolean CModQ3_LoadMarksurfaces (model_t *loadmodel, qbyte *mod_base, lump_t *l) { @@ -4101,7 +4088,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole noerrors = noerrors && CModQ3_LoadSubmodels (mod, mod_base, &header.lumps[Q3LUMP_MODELS]); noerrors = noerrors && CModQ3_LoadVisibility (mod, mod_base, &header.lumps[Q3LUMP_VISIBILITY]); if (noerrors) - CMod_LoadEntityString (mod, mod_base, &header.lumps[Q3LUMP_ENTITIES]); + Mod_LoadEntities (mod, mod_base, &header.lumps[Q3LUMP_ENTITIES]); if (!noerrors) { @@ -4203,7 +4190,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole noerrors = noerrors && CModQ2_LoadAreas (mod, mod_base, &header.lumps[Q2LUMP_AREAS]); noerrors = noerrors && CModQ2_LoadAreaPortals (mod, mod_base, &header.lumps[Q2LUMP_AREAPORTALS]); if (noerrors) - CMod_LoadEntityString (mod, mod_base, &header.lumps[Q2LUMP_ENTITIES]); + Mod_LoadEntities (mod, mod_base, &header.lumps[Q2LUMP_ENTITIES]); #ifndef CLIENTONLY mod->funcs.FatPVS = Q2BSP_FatPVS; @@ -4234,7 +4221,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole noerrors = noerrors && CModQ2_LoadPlanes (mod, mod_base, &header.lumps[Q2LUMP_PLANES]); noerrors = noerrors && CModQ2_LoadTexInfo (mod, mod_base, &header.lumps[Q2LUMP_TEXINFO], loadname); if (noerrors) - CMod_LoadEntityString (mod, mod_base, &header.lumps[Q2LUMP_ENTITIES]); + Mod_LoadEntities (mod, mod_base, &header.lumps[Q2LUMP_ENTITIES]); noerrors = noerrors && CModQ2_LoadFaces (mod, mod_base, &header.lumps[Q2LUMP_FACES], header.version == BSPVERSION_Q2W); noerrors = noerrors && Mod_LoadMarksurfaces (mod, mod_base, &header.lumps[Q2LUMP_LEAFFACES], false); noerrors = noerrors && CModQ2_LoadVisibility (mod, mod_base, &header.lumps[Q2LUMP_VISIBILITY]); @@ -4310,7 +4297,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole Q_snprintfz (name, sizeof(name), "*%i:%s", i, wmod->name); mod = Mod_FindName (name); *mod = *wmod; - mod->entities = NULL; + mod->entities_raw = NULL; mod->submodelof = wmod; Q_strncpyz(mod->name, name, sizeof(mod->name)); memset(&mod->memgroup, 0, sizeof(mod->memgroup)); diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 990ff04bd..86862532c 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -764,7 +764,14 @@ enum terrainedit_e // ter_autopaint_h, //vector pos, float radius, float percent, string tex1, string tex2 (paint tex1/tex2 // ter_autopaint_n //vector pos, float radius, float percent, string tex1, string tex2 - ter_tex_mask //string tex + ter_tex_mask, //string tex + + ter_ent_get, //int idx -> string + ter_ent_set, //int idx, string keyvals + ter_ent_add, //string keyvals -> int + ter_ent_count, // -> int + +// ter_cmd_count }; #endif diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index 06854bfeb..2cb49063a 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -4825,22 +4825,38 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g switch(action) { + case ter_ent_get: + { + int idx = G_INT(OFS_PARM1); + G_INT(OFS_RETURN) = 0; + } + return; + case ter_ent_set: + { + int idx = G_INT(OFS_PARM1); + const char *news = PR_GetStringOfs(prinst, OFS_PARM2); + G_INT(OFS_RETURN) = 0; + } + return; case ter_ents_wipe: - G_INT(OFS_RETURN) = PR_TempString(prinst, mod->entities); - mod->entities = Z_Malloc(1); + G_INT(OFS_RETURN) = PR_TempString(prinst, Mod_GetEntitiesString(mod)); + Mod_SetEntitiesString(mod, "", true); return; case ter_ents_concat: { - char *olds = mod->entities; + char *newv; + const char *olds = Mod_GetEntitiesString(mod); const char *news = PR_GetStringOfs(prinst, OFS_PARM1); size_t oldlen = strlen(olds); size_t newlen = strlen(news); - mod->entities = Z_Malloc(oldlen + newlen + 1); - memcpy(mod->entities, olds, oldlen); - memcpy(mod->entities+oldlen, news, newlen); - mod->entities[oldlen + newlen] = 0; - Z_Free(olds); + newv = Z_Malloc(oldlen + newlen + 1); + memcpy(newv, olds, oldlen); + memcpy(newv+oldlen, news, newlen); + newv[oldlen + newlen] = 0; + Z_Free((char*)olds); G_FLOAT(OFS_RETURN) = oldlen + newlen; + + Mod_SetEntitiesString(mod, newv, false); if (mod->terrain) { hm = mod->terrain; @@ -4849,7 +4865,7 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g } return; case ter_ents_get: - G_INT(OFS_RETURN) = PR_TempString(prinst, mod->entities); + G_INT(OFS_RETURN) = PR_TempString(prinst, Mod_GetEntitiesString(mod)); return; case ter_save: if (mod->terrain) @@ -5087,10 +5103,11 @@ void QCBUILTIN PF_terrain_edit(pubprogfuncs_t *prinst, struct globalvars_s *pr_g } #endif -void Terr_ParseEntityLump(char *data, heightmap_t *heightmap) +void Terr_ParseEntityLump(model_t *mod, heightmap_t *heightmap) { char key[128]; char value[2048]; + const char *data = Mod_GetEntitiesString(mod); heightmap->sectionsize = 1024; heightmap->mode = HMM_TERRAIN; @@ -5309,7 +5326,7 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e) if (mod->submodelof) mod = mod->submodelof; hm->entsdirty = false; - LightReloadEntities(hm->relightcontext, mod->entities, true); + LightReloadEntities(hm->relightcontext, Mod_GetEntitiesString(mod), true); //FIXME: figure out some way to hint this without having to relight the entire frigging world. for (bt = hm->brushtextures; bt; bt = bt->next) @@ -6685,7 +6702,7 @@ void Terr_WriteMapFile(vfsfile_t *file, model_t *mod) { char token[8192]; int nest = 0; - const char *start, *entities = mod->entities; + const char *start, *entities = Mod_GetEntitiesString(mod); int i; unsigned int entnum = 0; heightmap_t *hm; @@ -6803,7 +6820,8 @@ void Mod_Terrain_Save_f(void) Con_Printf("unable to open %s\n", fname); else { - VFS_WRITE(file, mod->entities, strlen(mod->entities)); + const char *s = Mod_GetEntitiesString(mod); + VFS_WRITE(file, s, strlen(s)); VFS_CLOSE(file); } } @@ -6826,7 +6844,7 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities) char token[8192]; int nest = 0; int buflen = strlen(entities); - char *out, *start; + char *out, *outstart, *start; int i; int submodelnum = 0; qboolean isdetail = false; @@ -6847,7 +6865,7 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities) #endif /*FIXME: we need to re-form the entities lump to insert model fields as appropriate*/ - mod->entities = out = Z_Malloc(buflen+1); + outstart = out = Z_Malloc(buflen+1); while(entities) { @@ -6914,8 +6932,7 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities) if (submod->loadstate == MLS_NOTLOADED) { submod->type = mod_heightmap; - if (!submod->entities) - submod->entities = Z_Malloc(1); + Mod_SetEntitiesString(submod, "", true); subhm = submod->terrain = Mod_LoadTerrainInfo(submod, submod->name, true); subhm->exteriorcontents = FTECONTENTS_EMPTY; @@ -7149,7 +7166,9 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities) while(start < entities) *out++ = *start++; } - *out++ = 0; + *out = 0; + + Mod_SetEntitiesString(mod, outstart, false); mod->numsubmodels = submodelnum; @@ -7209,7 +7228,7 @@ qboolean QDECL Terr_LoadTerrainModel (model_t *mod, void *buffer, size_t bufsize } hm->exteriorcontents = exterior; //sky outside the map - Terr_ParseEntityLump(mod->entities, hm); + Terr_ParseEntityLump(mod, hm); if (hm->firstsegx != hm->maxsegx) { @@ -7252,7 +7271,7 @@ qboolean QDECL Terr_LoadTerrainModel (model_t *mod, void *buffer, size_t bufsize #ifdef RUNTIMELIGHTING if (hm->relightcontext) { - LightReloadEntities(hm->relightcontext, mod->entities, true); + LightReloadEntities(hm->relightcontext, Mod_GetEntitiesString(mod), true); hm->entsdirty = false; } #endif @@ -7265,11 +7284,11 @@ void *Mod_LoadTerrainInfo(model_t *mod, char *loadname, qboolean force) { heightmap_t *hm; heightmap_t potential; - if (!mod->entities) + if (!Mod_GetEntitiesString(mod)) return NULL; memset(&potential, 0, sizeof(potential)); - Terr_ParseEntityLump(mod->entities, &potential); + Terr_ParseEntityLump(mod, &potential); if (potential.firstsegx >= potential.maxsegx || potential.firstsegy >= potential.maxsegy) { @@ -7347,7 +7366,7 @@ void Mod_Terrain_Create_f(void) groundheight = Cmd_Argv(5); if (!*groundheight) groundheight = "0"; watername = Cmd_Argv(6); if (!*watername) watername = ""; waterheight = Cmd_Argv(7); if (!*waterheight) waterheight = "1024"; - mod.entities = va( + Mod_SetEntitiesString(&mod, va( "{\n" "classname \"worldspawn\"\n" "message \"%s\"\n" @@ -7368,11 +7387,11 @@ void Mod_Terrain_Create_f(void) "classname info_player_start\n" "origin \"0 0 1024\"\n" "}\n" - , Cmd_Argv(2)); + , Cmd_Argv(2)), true); mod.type = mod_heightmap; mod.terrain = hm = Z_Malloc(sizeof(*hm)); - Terr_ParseEntityLump(mod.entities, hm); + Terr_ParseEntityLump(&mod, hm); hm->entitylock = Sys_CreateMutex(); ClearLink(&hm->recycle); Q_strncpyz(hm->path, Cmd_Argv(1), sizeof(hm->path)); @@ -7411,6 +7430,7 @@ void Mod_Terrain_Create_f(void) Con_Printf("Wrote %s\n", mname); FS_FlushFSHashWritten(); } + Mod_SetEntitiesString(&mod, NULL, false); Terr_FreeModel(&mod); } #endif diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index c65df7416..3401d04b3 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -449,6 +449,50 @@ void Mod_ResortShaders(void) } } } + +const char *Mod_GetEntitiesString(model_t *mod) +{ + if (!mod) + return NULL; + if (mod->entities_raw) //still cached/correct + return mod->entities_raw; + if (!mod->numentityinfo) + return NULL; + //reform the entities back into a full string now that we apparently need it + return mod->entities_raw; +} +void Mod_SetEntitiesString(model_t *mod, const char *str, qboolean docopy) +{ + size_t j; + for (j = 0; j < mod->numentityinfo; j++) + Z_Free(mod->entityinfo[j].keyvals); + mod->numentityinfo = 0; + Z_Free(mod->entityinfo); + mod->entityinfo = NULL; + Z_Free((char*)mod->entities_raw); + mod->entities_raw = NULL; + + if (str) + { + if (docopy) + str = Z_StrDup(str); + mod->entities_raw = str; + } +} + +void Mod_SetEntitiesStringLen(model_t *mod, const char *str, size_t strsize) +{ + if (str) + { + char *cpy = BZ_Malloc(strsize+1); + memcpy(cpy, str, strsize); + cpy[strsize] = 0; + Mod_SetEntitiesString(mod, cpy, false); + } + else + Mod_SetEntitiesString(mod, str, false); +} + /* =================== Mod_ClearAll @@ -538,8 +582,7 @@ void Mod_Purge(enum mod_purge_e ptype) mod->meshinfo = NULL; } - Z_Free(mod->entities); - mod->entities = NULL; + Mod_SetEntitiesString(mod, NULL, false); #ifdef PSET_SCRIPT PScript_ClearSurfaceParticles(mod); @@ -2088,10 +2131,11 @@ void Mod_LoadVisibility (model_t *loadmodel, qbyte *mod_base, lump_t *l, qbyte * } //scans through the worldspawn for a single specific key. -char *Mod_ParseWorldspawnKey(const char *ents, const char *key, char *buffer, size_t sizeofbuffer) +const char *Mod_ParseWorldspawnKey(model_t *mod, const char *key, char *buffer, size_t sizeofbuffer) { char keyname[64]; char value[1024]; + const char *ents = Mod_GetEntitiesString(mod); while(ents && *ents) { ents = COM_ParseOut(ents, keyname, sizeof(keyname)); @@ -2120,6 +2164,7 @@ static void Mod_SaveEntFile_f(void) char fname[MAX_QPATH]; model_t *mod = NULL; char *n = Cmd_Argv(1); + const char *ents; if (*n) mod = Mod_ForName(n, MLV_WARN); #ifndef CLIENTONLY @@ -2137,7 +2182,8 @@ static void Mod_SaveEntFile_f(void) Con_Printf("Map not loaded\n"); return; } - if (!mod->entities) + ents = Mod_GetEntitiesString(mod); + if (!ents) { Con_Printf("Map is not a map, and has no entities\n"); return; @@ -2155,7 +2201,7 @@ static void Mod_SaveEntFile_f(void) Q_strncatz(fname, ".ent", sizeof(fname)); } - COM_WriteFile(fname, FS_GAMEONLY, mod->entities, strlen(mod->entities)); + COM_WriteFile(fname, FS_GAMEONLY, ents, strlen(ents)); } /* @@ -2169,46 +2215,46 @@ void Mod_LoadEntities (model_t *loadmodel, qbyte *mod_base, lump_t *l) size_t sz; char keyname[64]; char value[1024]; - char *ents, *k; + char *ents = NULL, *k; int t; - loadmodel->entitiescrc = 0; - loadmodel->entities = NULL; + Mod_SetEntitiesString(loadmodel, NULL, false); if (!l->filelen) return; - if (mod_loadentfiles.value && !loadmodel->entities && *mod_loadentfiles_dir.string) + if (mod_loadentfiles.value && !ents && *mod_loadentfiles_dir.string) { if (!strncmp(loadmodel->name, "maps/", 5)) { Q_snprintfz(fname, sizeof(fname), "maps/%s/%s", mod_loadentfiles_dir.string, loadmodel->name+5); COM_StripExtension(fname, fname, sizeof(fname)); Q_strncatz(fname, ".ent", sizeof(fname)); - loadmodel->entities = FS_LoadMallocFile(fname, &sz); + ents = FS_LoadMallocFile(fname, &sz); } } - if (mod_loadentfiles.value && !loadmodel->entities) + if (mod_loadentfiles.value && !ents) { COM_StripExtension(loadmodel->name, fname, sizeof(fname)); Q_strncatz(fname, ".ent", sizeof(fname)); - loadmodel->entities = FS_LoadMallocFile(fname, &sz); + ents = FS_LoadMallocFile(fname, &sz); } - if (mod_loadentfiles.value && !loadmodel->entities) + if (mod_loadentfiles.value && !ents) { //tenebrae compat COM_StripExtension(loadmodel->name, fname, sizeof(fname)); Q_strncatz(fname, ".edo", sizeof(fname)); - loadmodel->entities = FS_LoadMallocFile(fname, &sz); + ents = FS_LoadMallocFile(fname, &sz); } - if (!loadmodel->entities) + if (!ents) { - loadmodel->entities = Z_Malloc(l->filelen + 1); - memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen); - loadmodel->entities[l->filelen] = 0; + ents = Z_Malloc(l->filelen + 1); + memcpy (ents, mod_base + l->fileofs, l->filelen); + ents[l->filelen] = 0; } else - loadmodel->entitiescrc = QCRC_Block(loadmodel->entities, strlen(loadmodel->entities)); + loadmodel->entitiescrc = QCRC_Block(ents, strlen(ents)); + + Mod_SetEntitiesString(loadmodel, ents, false); - ents = loadmodel->entities; while(ents && *ents) { ents = COM_ParseOut(ents, keyname, sizeof(keyname)); @@ -2579,7 +2625,7 @@ qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, lump_t * memset(&overrides, 0, sizeof(overrides)); - lmscale = atoi(Mod_ParseWorldspawnKey(loadmodel->entities, "lightmap_scale", buf, sizeof(buf))); + lmscale = atoi(Mod_ParseWorldspawnKey(loadmodel, "lightmap_scale", buf, sizeof(buf))); if (!lmscale) lmshift = LMSHIFT_DEFAULT; else @@ -4880,7 +4926,7 @@ TRACE(("LoadBrushModel %i\n", __LINE__)); submod->numclusters = bm->visleafs; if (i) - submod->entities = NULL; + submod->entities_raw = NULL; memset(&submod->batches, 0, sizeof(submod->batches)); submod->vbos = NULL; @@ -4916,7 +4962,7 @@ TRACE(("LoadBrushModel %i\n", __LINE__)); if (lightmodel == mod) { lightcontext = LightStartup(NULL, lightmodel, true); - LightReloadEntities(lightcontext, lightmodel->entities, false); + LightReloadEntities(lightcontext, Mod_GetEntitiesString(lightmodel), false); } #endif TRACE(("LoadBrushModel %i\n", __LINE__)); diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 91af342a4..dcbfc35c6 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -953,7 +953,9 @@ typedef struct model_s q3lightgridinfo_t *lightgrid; mfog_t *fogs; int numfogs; - char *entities; + struct {char *keyvals;} *entityinfo; + size_t numentityinfo; + const char *entities_raw; int entitiescrc; struct doll_s *dollinfo; diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 7ad9514d2..54d6ac509 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -694,7 +694,7 @@ void R_PushDlights (void) //rtlight loading #ifdef RTLIGHTS -qboolean R_ImportRTLights(char *entlump) +qboolean R_ImportRTLights(const char *entlump) { typedef enum lighttype_e {LIGHTTYPE_MINUSX, LIGHTTYPE_RECIPX, LIGHTTYPE_RECIPXX, LIGHTTYPE_NONE, LIGHTTYPE_SUN, LIGHTTYPE_MINUSXX} lighttype_t; @@ -1257,14 +1257,14 @@ void R_ReloadRTLights_f(void) rtlights_first = RTL_FIRST; rtlights_max = RTL_FIRST; if (!strcmp(Cmd_Argv(1), "bsp")) - R_ImportRTLights(cl.worldmodel->entities); + R_ImportRTLights(Mod_GetEntitiesString(cl.worldmodel)); else if (!strcmp(Cmd_Argv(1), "rtlights")) R_LoadRTLights(); else if (strcmp(Cmd_Argv(1), "none")) { R_LoadRTLights(); if (rtlights_first == rtlights_max) - R_ImportRTLights(cl.worldmodel->entities); + R_ImportRTLights(Mod_GetEntitiesString(cl.worldmodel)); } for (i = 0; i < cl.num_statics; i++) diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 125d53807..2b37c2c30 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -1762,7 +1762,7 @@ void GLR_RenderView (void) double time1 = 0, time2; texid_t sourcetex = r_nulltex; shader_t *custompostproc = NULL; - float renderscale = r_renderscale.value; //extreme, but whatever + float renderscale; //extreme, but whatever int oldfbo = 0; checkglerror(); @@ -1790,9 +1790,16 @@ void GLR_RenderView (void) Surf_SetupFrame(); r_refdef.flags &= ~(RDF_ALLPOSTPROC|RDF_RENDERSCALE); - if (!(r_refdef.flags & RDF_NOWORLDMODEL)) + if (dofbo || (r_refdef.flags & RDF_NOWORLDMODEL)) + { + renderscale = 1; + } + else + { + renderscale = r_renderscale.value; if (R_CanBloom()) r_refdef.flags |= RDF_BLOOM; + } //check if we can do underwater warp if (cls.protocol != CP_QUAKE2) //quake2 tells us directly diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 3c4334737..4c7e3bfc8 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -719,9 +719,12 @@ texid_t R_LoadColourmapImage(void) { size_t sz; qbyte *pcx = FS_LoadMallocFile("pics/colormap.pcx", &sz); - colourmappal = Z_Malloc(256*VID_GRADES); - ReadPCXData(pcx, sz, 256, VID_GRADES, colourmappal); - BZ_Free(pcx); + if (pcx) + { + colourmappal = Z_Malloc(256*VID_GRADES); + ReadPCXData(pcx, sz, 256, VID_GRADES, colourmappal); + BZ_Free(pcx); + } } if (colourmappal) { @@ -730,8 +733,17 @@ texid_t R_LoadColourmapImage(void) } else { //erk + //fixme: generate a proper colourmap for (x = 0; x < sizeof(data)/sizeof(data[0]); x++) - data[x] = d_8to24rgbtable[x & 0xff]; + { + int r, g, b; + float l = 1.0-((x/256)/(float)VID_GRADES); + r = d_8to24rgbtable[x & 0xff]; + g = (r>>16)&0xff; + b = (r>>8)&0xff; + r = (r>>0)&0xff; + data[x] = d_8to24rgbtable[GetPaletteIndex(r*l,g*l,b*l)]; + } } BZ_Free(colourmappal); return R_LoadTexture("$colourmap", w, h, TF_RGBA32, data, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA|IF_CLAMP); @@ -4960,11 +4972,10 @@ void QDECL R_BuildDefaultTexnums(texnums_t *src, shader_t *shader) if ((shader->flags & SHADER_HASPALETTED) && !TEXVALID(tex->paletted)) { - /*dlights/realtime lighting needs some stuff*/ -// if (!TEXVALID(tex->paletted) && *tex->mapname) -// tex->paletted = R_LoadHiResTexture(va("%s_pal", tex->mapname), NULL, 0|IF_NEAREST); -// if (!TEXVALID(tex->paletted)) -// tex->paletted = R_LoadHiResTexture(va("%s_pal", imagename), subpath, ((*imagename=='{')?0:IF_NOALPHA)|IF_NEAREST); + if (!TEXVALID(tex->paletted) && *tex->mapname) + tex->paletted = R_LoadHiResTexture(va("%s", tex->mapname), NULL, 0|IF_NEAREST|IF_PALETTIZE); + if (!TEXVALID(tex->paletted)) + tex->paletted = R_LoadHiResTexture(va("%s", imagename), subpath, ((*imagename=='{')?0:IF_NOALPHA)|IF_NEAREST|IF_PALETTIZE); } imageflags |= IF_LOWPRIORITY; @@ -5229,6 +5240,16 @@ void Shader_DefaultBSPLM(const char *shortname, shader_t *s, const void *args) if (Shader_ParseShader("defaultwall", s)) return; + if (!builtin && r_softwarebanding && (qrenderer == QR_OPENGL || qrenderer == QR_VULKAN) && sh_config.progs_supported) + builtin = ( + "{\n" + "{\n" + "program defaultwall#EIGHTBIT\n" + "map $colourmap\n" + "}\n" + "}\n" + ); + if (!builtin && r_lightmap.ival) builtin = ( "{\n" @@ -5605,17 +5626,6 @@ void Shader_DefaultBSPQ2(const char *shortname, shader_t *s, const void *args) "}\n" ); } - else if (r_softwarebanding && (qrenderer == QR_OPENGL || qrenderer == QR_VULKAN) && sh_config.progs_supported) - { - Shader_DefaultScript(shortname, s, - "{\n" - "program defaultwall#EIGHTBIT\n" - "{\n" - "map $colourmap\n" - "}\n" - "}\n" - ); - } else Shader_DefaultBSPLM(shortname, s, args); } @@ -5766,19 +5776,6 @@ void Shader_DefaultBSPQ1(const char *shortname, shader_t *s, const void *args) ); } - if (!builtin && r_softwarebanding) - { - /*alpha bended*/ - builtin = ( - "{\n" - "program defaultwall#EIGHTBIT\n" - "{\n" - "map $colourmap\n" - "}\n" - "}\n" - ); - } - if (builtin) Shader_DefaultScript(shortname, s, builtin); else @@ -5843,6 +5840,20 @@ void Shader_DefaultSkin(const char *shortname, shader_t *s, const void *args) if (Shader_ParseShader("defaultskin", s)) return; + if (r_softwarebanding && qrenderer == QR_OPENGL && sh_config.progs_supported) + { + Shader_DefaultScript(shortname, s, + "{\n" + "program defaultskin#EIGHTBIT\n" + "affine\n" + "{\n" + "map $colourmap\n" + "}\n" + "}\n" + ); + return; + } + Shader_DefaultScript(shortname, s, "{\n" "if $lpp\n" diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index b48d19b21..cb8effbfc 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -3435,7 +3435,7 @@ void Sh_PreGenerateLights(void) if (!okay) okay |= R_LoadRTLights(); if (!okay) - okay |= R_ImportRTLights(cl.worldmodel->entities); + okay |= R_ImportRTLights(Mod_GetEntitiesString(cl.worldmodel)); if (!okay && r_shadow_realtime_world.ival && r_shadow_realtime_world_lightmaps.value != 1) { r_shadow_realtime_world_lightmaps.value = 1; diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 7ef747837..8568aea53 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -402,7 +402,7 @@ void GLR_MarkQ2Lights (dlight_t *light, int bit, mnode_t *node); void GLQ3_LightGrid(model_t *mod, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); void R_ReloadRTLights_f(void); qboolean R_LoadRTLights(void); -qboolean R_ImportRTLights(char *entlump); +qboolean R_ImportRTLights(const char *entlump); void R_SaveRTLights_f(void); //doom diff --git a/engine/gl/ltface.c b/engine/gl/ltface.c index 6836a9e31..329647230 100644 --- a/engine/gl/ltface.c +++ b/engine/gl/ltface.c @@ -144,7 +144,7 @@ struct relight_ctx_s *LightStartup(struct relight_ctx_s *ctx, model_t *model, qb ctx->models[ctx->nummodels++] = model; return ctx; } -void LightReloadEntities(struct relight_ctx_s *ctx, char *entstring, qboolean ignorestyles) +void LightReloadEntities(struct relight_ctx_s *ctx, const char *entstring, qboolean ignorestyles) { #define DEFAULTLIGHTLEVEL 300 mentity_t *mapent; diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index 20703e6a1..b5b66568a 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -4482,6 +4482,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND #endif #ifdef GLQUAKE {QR_OPENGL, 110, "defaultwall", +"!!ver 110 130\n" "!!permu DELUXE\n" "!!permu FULLBRIGHT\n" "!!permu FOG\n" @@ -4494,6 +4495,12 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#include \"sys/defs.h\"\n" +"#if GL_VERSION >= 130\n" +"#define texture2D texture\n" +"#define textureCube texture\n" +"#define gl_FragColor gl_FragData[0]\n" +"#endif\n" + //this is what normally draws all of your walls, even with rtlights disabled //note that the '286' preset uses drawflat_walls instead. @@ -4578,7 +4585,13 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND //optional: round the lightmap coords to ensure all pixels within a texel have different lighting values either. it just looks wrong otherwise. //don't bother if its lightstyled, such cases will have unpredictable correlations anyway. //FIXME: this rounding is likely not correct with respect to software rendering. oh well. -"vec2 lmcoord0 = floor(lm0 * 512.0*16.0)/(512.0*16.0);\n" +"#if GL_VERSION >= 130\n" +"vec2 lmsize = vec2(textureSize(s_lightmap0, 0));\n" +"#else\n" +"#define lmsize vec2(128.0,2048.0)\n" +"#endif\n" +"#define texelstolightmap (16.0)\n" +"vec2 lmcoord0 = floor(lm0 * lmsize*texelstolightmap)/(lmsize*texelstolightmap);\n" "#define lm0 lmcoord0\n" "#endif\n" @@ -4675,6 +4688,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" "}\n" "#endif\n" + }, #endif #ifdef VKQUAKE diff --git a/engine/server/botlib.h b/engine/server/botlib.h index 29b1f4e39..7a3e74a85 100644 --- a/engine/server/botlib.h +++ b/engine/server/botlib.h @@ -179,7 +179,7 @@ typedef struct botlib_import_s //check if the point is in potential visible sight int (QDECL *inPVS)(vec3_t p1, vec3_t p2); //retrieve the BSP entity data lump - char *(QDECL *BSPEntityData)(void); + const char *(QDECL *BSPEntityData)(void); // void (QDECL *BSPModelMinsMaxsOrigin)(int modelnum, vec3_t angles, vec3_t mins, vec3_t maxs, vec3_t origin); //send a bot client command diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index b1e5150b5..d569a0f1d 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -781,7 +781,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents, { extern cvar_t allow_download_refpackages; func_t f; - char *file; + const char *file; extern cvar_t pr_maxedicts; gametype_e newgametype; @@ -1451,7 +1451,7 @@ void SV_SpawnServer (const char *server, const char *startspot, qboolean noents, else Info_SetValueForStarKey(svs.info, "*entfile", "", MAX_SERVERINFO_STRING); - file = sv.world.worldmodel->entities; + file = Mod_GetEntitiesString(sv.world.worldmodel); if (!file) file = ""; diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index 1c977c194..a1f608961 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -80,7 +80,7 @@ void SVQ3_CreateBaseline(void); void SVQ3_ClientThink(client_t *cl); void SVQ3Q1_ConvertEntStateQ1ToQ3(entity_state_t *q1, q3entityState_t *q3); -char *mapentspointer; +const char *mapentspointer; #define Q3SOLID_BMODEL 0xffffff @@ -1614,9 +1614,9 @@ static int QDECL BL_Seek(fileHandle_t f, long offset, int seektype) { // on success, apparently returns 0 return VM_FSeek((int)f, offset, seektype, Z_TAG_BOTLIB)?0:-1; } -static char *QDECL BL_BSPEntityData(void) +static const char *QDECL BL_BSPEntityData(void) { - return sv.world.worldmodel->entities; + return Mod_GetEntitiesString(sv.world.worldmodel); } static void QDECL BL_Trace(bsp_trace_t *trace, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int passent, int contentmask) { @@ -1836,7 +1836,7 @@ qboolean SVQ3_InitGame(void) SVQ3_SetConfigString(1, sysinfo); - mapentspointer = sv.world.worldmodel->entities; + mapentspointer = Mod_GetEntitiesString(sv.world.worldmodel); VM_Call(q3gamevm, GAME_INIT, 0, (int)rand(), false); CM_InitBoxHull(); diff --git a/engine/shaders/glsl/defaultwall.glsl b/engine/shaders/glsl/defaultwall.glsl index 75d445d07..84ad91e5c 100644 --- a/engine/shaders/glsl/defaultwall.glsl +++ b/engine/shaders/glsl/defaultwall.glsl @@ -1,3 +1,4 @@ +!!ver 110 130 !!permu DELUXE !!permu FULLBRIGHT !!permu FOG @@ -10,6 +11,12 @@ #include "sys/defs.h" +#if GL_VERSION >= 130 +#define texture2D texture +#define textureCube texture +#define gl_FragColor gl_FragData[0] +#endif + //this is what normally draws all of your walls, even with rtlights disabled //note that the '286' preset uses drawflat_walls instead. @@ -94,7 +101,13 @@ void main () //optional: round the lightmap coords to ensure all pixels within a texel have different lighting values either. it just looks wrong otherwise. //don't bother if its lightstyled, such cases will have unpredictable correlations anyway. //FIXME: this rounding is likely not correct with respect to software rendering. oh well. - vec2 lmcoord0 = floor(lm0 * 512.0*16.0)/(512.0*16.0); +#if GL_VERSION >= 130 + vec2 lmsize = vec2(textureSize(s_lightmap0, 0)); +#else + #define lmsize vec2(128.0,2048.0) +#endif +#define texelstolightmap (16.0) + vec2 lmcoord0 = floor(lm0 * lmsize*texelstolightmap)/(lmsize*texelstolightmap); #define lm0 lmcoord0 #endif @@ -191,3 +204,4 @@ void main () #endif } #endif + diff --git a/engine/vk/vk_backend.c b/engine/vk/vk_backend.c index 87cb1325d..6fb5d325a 100644 --- a/engine/vk/vk_backend.c +++ b/engine/vk/vk_backend.c @@ -4293,8 +4293,8 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod) for (i = 0; i < MAXRLIGHTMAPS ; i++) { - //FIXME: this is fucked - /* + //FIXME: this is fucked, the batch isn't known yet. + #if 0 extern cvar_t gl_overbright; unsigned char s = shaderstate.curbatch?shaderstate.curbatch->lmlightstyle[i]:0; float sc; @@ -4321,13 +4321,15 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod) } break; } + #else + float sc = 1; + #endif if (shaderstate.curentity->model && shaderstate.curentity->model->engineflags & MDLF_NEEDOVERBRIGHT) sc = (1<e_lmscale[i], sc, sc, sc, 1); } diff --git a/engine/vk/vk_init.c b/engine/vk/vk_init.c index 3b99c248c..bd01b3164 100644 --- a/engine/vk/vk_init.c +++ b/engine/vk/vk_init.c @@ -3267,7 +3267,6 @@ void VK_Shutdown(void) Sys_DestroyConditional(vk.submitcondition); memset(&vk, 0, sizeof(vk)); - qrenderer = QR_NONE; #ifdef VK_NO_PROTOTYPES #define VKFunc(n) vk##n = NULL;