From f33873ddb71cc00fe08a167194e69f79673c9a7b Mon Sep 17 00:00:00 2001 From: Spoike Date: Thu, 27 Oct 2011 16:16:29 +0000 Subject: [PATCH] committing for fixes for OMC some minor changes. Mostly bug fixes and internal reorganisation. Added code to provide an activex control as part of the npfte.dll plugin. If the dll is registered the regsvr32 way, the plugin can be used with IE as well. fisheye/panoramic view enable is now controlled by rulesets instead of serverinfo. server will list all pak files it has loaded. client will probably do the wrong thing and still needs fixing properly. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3910 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/Makefile | 1 + engine/common/bothdefs.h | 1 - engine/common/bspfile.h | 55 +- engine/common/com_mesh.c | 146 +- engine/common/com_phys_ode.c | 6 +- engine/common/common.c | 37 + engine/common/common.h | 5 +- engine/common/cvar.c | 12 +- engine/common/fs.c | 253 +- engine/common/fs_pak.c | 32 +- engine/common/fs_zip.c | 8 +- engine/common/gl_q2bsp.c | 6 +- engine/common/mathlib.c | 29 +- engine/common/net.h | 13 +- engine/common/net_chan.c | 35 +- engine/common/net_wins.c | 69 +- engine/common/particles.h | 2 +- engine/common/pr_bgcmd.c | 53 +- engine/common/pr_common.h | 19 +- engine/common/protocol.h | 6 +- engine/common/world.h | 7 +- engine/d3d/d3d_backend.c | 64 +- engine/d3d/d3d_image.c | 81 +- engine/d3d/vid_d3d.c | 10 +- engine/dotnet2005/ftequake.vcproj | 8711 +++++++++++++++-------------- engine/dotnet2005/npfte.vcproj | 19 + engine/ftequake/npapi.def | 10 + engine/gl/gl_alias.c | 17 +- engine/gl/gl_backend.c | 441 +- engine/gl/gl_bloom.c | 6 +- engine/gl/gl_draw.c | 246 +- engine/gl/gl_draw.h | 1 - engine/gl/gl_font.c | 12 +- engine/gl/gl_hlmdl.c | 14 +- engine/gl/gl_model.c | 511 +- engine/gl/gl_model.h | 99 +- engine/gl/gl_ngraph.c | 79 +- engine/gl/gl_rlight.c | 29 +- engine/gl/gl_rmain.c | 366 +- engine/gl/gl_rmisc.c | 45 +- engine/gl/gl_rsurf.c | 5 +- engine/gl/gl_shader.c | 328 +- engine/gl/gl_shadow.c | 327 +- engine/gl/gl_vidcommon.c | 340 +- engine/gl/gl_vidlinuxglx.c | 22 +- engine/gl/gl_vidnt.c | 67 +- engine/gl/gl_warp.c | 6 + engine/gl/glquake.h | 35 +- engine/gl/glsupp.h | 4 + engine/gl/shader.h | 13 +- engine/qclib/initlib.c | 73 +- engine/qclib/pr_edict.c | 84 +- engine/qclib/pr_x86.c | 125 +- engine/qclib/progsint.h | 12 +- engine/qclib/progslib.h | 3 +- engine/qclib/qcc_pr_comp.c | 3 + engine/qclib/qccgui.c | 172 +- engine/qclib/qccmain.c | 10 +- engine/server/net_preparse.c | 4 +- engine/server/pr_cmds.c | 275 +- engine/server/pr_q1qvm.c | 24 +- engine/server/progdefs.h | 8 +- engine/server/progs.h | 10 +- engine/server/savegame.c | 11 +- engine/server/server.h | 8 +- engine/server/sv_ccmds.c | 34 +- engine/server/sv_ents.c | 35 +- engine/server/sv_init.c | 30 +- engine/server/sv_main.c | 163 +- engine/server/sv_phys.c | 46 +- engine/server/sv_send.c | 15 +- engine/server/sv_user.c | 426 +- engine/server/svhl_phys.c | 5 +- engine/server/svmodel.c | 329 +- engine/server/svq2_game.c | 2 +- engine/server/svq3_game.c | 26 +- engine/server/world.c | 8 +- specs/browserexample.html | 10 +- 78 files changed, 7999 insertions(+), 6655 deletions(-) diff --git a/engine/Makefile b/engine/Makefile index 7edb0e709..613b55c98 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -327,6 +327,7 @@ CLIENT_OBJS = \ cl_cg.o \ clq3_parse.o \ pr_csqc.o \ + pr_skelobj.o \ console.o \ image.o \ keys.o \ diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 40d38e5be..e586cd527 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -185,7 +185,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // #define HLCLIENT 7 //we can run HL gamecode (not protocol compatible, set to 6 or 7) // #define HLSERVER 140 //we can run HL gamecode (not protocol compatible, set to 138 or 140) #define NQPROT //server and client are capable of using quake1/netquake protocols. (qw is still prefered. uses the command 'nqconnect') - #define FISH //fisheye distortion stuff #define ZLIB //zip/pk3 support #define WEBSERVER //http/ftp servers #define WEBCLIENT //http/ftp clients. diff --git a/engine/common/bspfile.h b/engine/common/bspfile.h index b68c7010e..0b9e5ead6 100644 --- a/engine/common/bspfile.h +++ b/engine/common/bspfile.h @@ -56,6 +56,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define BSPVERSION 29 //HalfLife support #define BSPVERSIONHL 30 +#define BSPVERSION_LONG (('B' << 24) | ('S' << 16) | ('P' << 8) | '2') /*RMQ support. 32bits instead of shorts for all but bbox sizes*/ typedef struct { @@ -169,13 +170,27 @@ typedef struct short maxs[3]; unsigned short firstface; unsigned short numfaces; // counting both sides -} dnode_t; +} dsnode_t; +typedef struct +{ + int planenum; + int children[2]; // negative numbers are -(leafs+1), not nodes + short mins[3]; // for sphere culling + short maxs[3]; + unsigned int firstface; + unsigned int numfaces; // counting both sides +} dlnode_t; typedef struct { int planenum; short children[2]; // negative numbers are contents -} dclipnode_t; +} dsclipnode_t; +typedef struct +{ + int planenum; + int children[2]; // negative numbers are contents +} dlclipnode_t; typedef struct { @@ -196,7 +211,11 @@ typedef struct texinfo_s typedef struct { unsigned short v[2]; // vertex numbers -} dedge_t; +} dsedge_t; +typedef struct +{ + unsigned short v[2]; // vertex numbers +} dledge_t; #define MAXLIGHTMAPS 4 typedef struct @@ -211,7 +230,20 @@ typedef struct // lighting info qbyte styles[MAXLIGHTMAPS]; int lightofs; // start of [numstyles*surfsize] samples -} dface_t; +} dsface_t; +typedef struct +{ + int planenum; + int side; + + int firstedge; // we must support > 64k edges + int numedges; + int texinfo; + +// lighting info + qbyte styles[MAXLIGHTMAPS]; + int lightofs; // start of [numstyles*surfsize] samples +} dlface_t; @@ -236,7 +268,20 @@ typedef struct unsigned short nummarksurfaces; qbyte ambient_level[NUM_AMBIENTS]; -} dleaf_t; +} dsleaf_t; +typedef struct +{ + int contents; + int visofs; // -1 = no visibility info + + short mins[3]; // for frustum culling + short maxs[3]; + + unsigned int firstmarksurface; + unsigned int nummarksurfaces; + + qbyte ambient_level[NUM_AMBIENTS]; +} dlleaf_t; //============================================================================ diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index ba8b1b213..8d3f19f41 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -4,6 +4,8 @@ extern model_t *loadmodel; extern char loadname[]; +qboolean r_loadbumpmapping; +extern cvar_t dpcompat_psa_ungroup; //Common loader function. void Mod_DoCRC(model_t *mod, char *buffer, int buffersize) @@ -103,8 +105,8 @@ clampedmodel_t clampedmodel[] = { {"progs/s_explod.spr", 1000}, //and now TF models -#ifndef _MSC_VER -#warning FIXME: these are placeholders +#ifdef warningmsg +#pragma warningmsg("FIXME: these are placeholders") #endif {"progs/disp.mdl", 3000}, {"progs/tf_flag.mdl", 3000}, @@ -339,6 +341,7 @@ static void PSKGenMatrix(float x, float y, float z, float qx, float qy, float qz #define restrict +#if 0 /*transforms some skeletal vecV_t values*/ static void Alias_TransformVerticies_V(float *bonepose, int vertcount, qbyte *bidx, float *weights, float *xyzin, float *restrict xyzout) { @@ -376,6 +379,7 @@ static void Alias_TransformVerticies_V(float *bonepose, int vertcount, qbyte *bi } } } +#endif /*transforms some skeletal vecV_t values*/ static void Alias_TransformVerticies_VN(float *bonepose, int vertcount, qbyte *bidx, float *weights, @@ -423,7 +427,7 @@ static void Alias_TransformVerticies_VN(float *bonepose, int vertcount, qbyte *b } } - +#if 0 /*transforms some skeletal vec3_t values*/ static void Alias_TransformVerticies_3(float *bonepose, int vertcount, qbyte *bidx, float *weights, float *xyzin, float *restrict xyzout) { @@ -461,6 +465,7 @@ static void Alias_TransformVerticies_3(float *bonepose, int vertcount, qbyte *bi } } } +#endif static void Alias_TransformVerticies_SW(float *bonepose, galisskeletaltransforms_t *weights, int numweights, vecV_t *xyzout, vec3_t *normout) { @@ -1084,7 +1089,6 @@ struct void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t *colours, int vertcount, vec3_t *normals) { - //extern cvar_t r_vertexdlights; //unused int i; int c; float l; @@ -1129,7 +1133,7 @@ void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t * } } -void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *normals) +void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *normals, float scale) { extern cvar_t r_vertexdlights; int i; @@ -1148,6 +1152,9 @@ void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int } else { + vec3_t la, lr; + VectorScale(entity->light_avg, scale, la); + VectorScale(entity->light_range, scale, lr); #ifdef SSE_INTRINSICS __m128 va, vs, vl, vr; va = _mm_load_ps(ambientlight); @@ -1167,9 +1174,9 @@ void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int _mm_storeu_ps(colours[i], vr); //stomp on colour[i][3] (will be set to 1) #else - colours[i][0] = l*entity->light_range[0]+entity->light_avg[0]; - colours[i][1] = l*entity->light_range[1]+entity->light_avg[1]; - colours[i][2] = l*entity->light_range[2]+entity->light_avg[2]; + colours[i][0] = l*lr[0]+la[0]; + colours[i][1] = l*lr[1]+la[1]; + colours[i][2] = l*lr[2]+la[2]; #endif } } @@ -2184,8 +2191,8 @@ static void *Alias_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremap pose->ofssvector = (char *)svec - (char *)pose; pose->ofstvector = (char *)tvec - (char *)pose; #else -#ifdef _MSC_VER -#pragma message("wasted memory") +#ifdef warningmsg +#pragma warningmsg("wasted memory") #endif #endif @@ -2366,7 +2373,6 @@ static void *Q1_LoadSkins_SV (daliasskintype_t *pskintype, qboolean alpha) #if defined(GLQUAKE) || defined(D3DQUAKE) static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintranstype) { - extern cvar_t gl_bump; texnums_t *texnums; char skinname[MAX_QPATH]; int i; @@ -2397,9 +2403,12 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran texture = R_LoadReplacementTexture(skinname, "models", IF_NOALPHA); if (TEXVALID(texture)) { - snprintf(skinname, sizeof(skinname), "%s_%i_luma", loadmodel->name, i); - fbtexture = R_LoadReplacementTexture(skinname, "models", 0); - if (gl_bump.ival) + if (TEXVALID(texture) && r_fb_models.ival) + { + snprintf(skinname, sizeof(skinname), "%s_%i_luma", loadmodel->name, i); + fbtexture = R_LoadReplacementTexture(skinname, "models", 0); + } + if (r_loadbumpmapping) { snprintf(skinname, sizeof(skinname), "%s_%i_bump", loadmodel->name, i); bumptexture = R_LoadBumpmapTexture(skinname, "models"); @@ -2414,7 +2423,7 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran snprintf(skinname, sizeof(skinname), "%s_%i_luma", loadname, i); fbtexture = R_LoadReplacementTexture(skinname, "models", 0); } - if (TEXVALID(texture) && gl_bump.ival) + if (TEXVALID(texture) && r_loadbumpmapping) { snprintf(skinname, sizeof(skinname), "%s_%i_bump", loadname, i); bumptexture = R_LoadBumpmapTexture(skinname, "models"); @@ -2444,7 +2453,7 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran snprintf(skinname, sizeof(skinname), "%s__%i_luma", loadname, i); fbtexture = R_LoadTextureFB(skinname, outskin->skinwidth, outskin->skinheight, saved, IF_NOGAMMA); } - if (gl_bump.ival) + if (r_loadbumpmapping) { snprintf(skinname, sizeof(skinname), "%s__%i_bump", loadname, i); bumptexture = R_LoadTexture8BumpPal(skinname, outskin->skinwidth, outskin->skinheight, saved, IF_NOGAMMA); @@ -2601,12 +2610,10 @@ static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, unsigned int skintran Q_snprintfz(skinname, sizeof(skinname), "%s_%i_%i", loadname, i, t); texnums->shader = R_RegisterSkin(skinname, loadmodel->name); - texnums->base = texture; - texnums->fullbright = fbtexture; - - //13/4/08 IMPLEMENTME - texnums->loweroverlay = r_nulltex; - texnums->upperoverlay = r_nulltex; + TEXASSIGN(texnums->base, texture); + TEXASSIGN(texnums->fullbright, fbtexture); + TEXASSIGN(texnums->loweroverlay, r_nulltex); + TEXASSIGN(texnums->upperoverlay, r_nulltex); R_BuildDefaultTexnums(texnums, texnums->shader); } @@ -2710,11 +2717,11 @@ qboolean Mod_LoadQ1Model (model_t *mod, void *buffer) //skins skinstart = (daliasskintype_t *)((char*)pq1inmodel+hdrsize); - if( mod->flags & EFH2_HOLEY ) + if( mod->flags & MFH2_HOLEY ) skintranstype = 3; //hexen2 - else if( mod->flags & EFH2_TRANSPARENT ) + else if( mod->flags & MFH2_TRANSPARENT ) skintranstype = 2; //hexen2 - else if( mod->flags & EFH2_SPECIAL_TRANS ) + else if( mod->flags & MFH2_SPECIAL_TRANS ) skintranstype = 4; //hexen2 else skintranstype = 0; @@ -2984,7 +2991,7 @@ static void Q2_LoadSkins(md2_t *pq2inmodel, char *skins) outskin->texnums=1; COM_CleanUpPath(skins); //blooming tanks. - texnums->base = R_LoadReplacementTexture(skins, "models", IF_NOALPHA); + TEXASSIGN(texnums->base, R_LoadReplacementTexture(skins, "models", IF_NOALPHA)); texnums->shader = R_RegisterSkin(skins, loadmodel->name); R_BuildDefaultTexnums(texnums, texnums->shader); @@ -3389,8 +3396,8 @@ qboolean Mod_GetTag(model_t *model, int tagnum, framestate_t *fstate, float *res float f1time, f2time; float f2ness; -#ifdef _MSC_VER -#pragma message("fixme") +#ifdef warningmsg +#pragma warningmsg("fixme: no base info") #endif frame1 = fstate->g[FS_REG].frame[0]; frame2 = fstate->g[FS_REG].frame[1]; @@ -4466,13 +4473,12 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) galiasskin_t *skin; texnums_t *gtexnums; #endif - galisskeletaltransforms_t *trans; galiasbone_t *bones; galiasgroup_t *group; float *animmatrix, *basematrix, *basematrix_inverse; - unsigned int num_trans; index_t *indexes; float vrad; + int bonemap[MAX_BONES]; pskpnts_t *pnts = NULL; pskvtxw_t *vtxw = NULL; @@ -4487,12 +4493,17 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) unsigned int num_animinfo=0, num_animkeys=0; int hunkstart, hunkend, hunktotal; - //extern cvar_t temp1; //unused variable +//#define PSK_GPU +#ifndef PSK_GPU + unsigned int num_trans; + galisskeletaltransforms_t *trans; +#else vecV_t *skel_xyz; vec3_t *skel_norm; byte_vec4_t *skel_idx; vec4_t *skel_weights; +#endif /*load the psk*/ while (pos < com_filesize && !fail) @@ -4573,7 +4584,7 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) boneinfo[i].basepose.size[2] = LittleFloat(boneinfo[i].basepose.size[2]); /*not sure if this is needed, but mimic DP*/ - if (i) + if (i >= 0) { boneinfo[i].basepose.quat[0] *= -1; boneinfo[i].basepose.quat[2] *= -1; @@ -4637,6 +4648,31 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) } else { + for (i = 0; i < num_boneinfo; i++) + { + /*assumption: 1:1 mapping will be common*/ + if (!strcmp(boneinfo[i].name, animbones[i].name)) + bonemap[i] = i; + else + { + /*non 1:1 mapping*/ + for (j = 0; j < chunk->numrecords; j++) + { + if (!strcmp(boneinfo[i].name, animbones[j].name)) + { + bonemap[i] = j; + break; + } + } + if (j == chunk->numrecords) + { + fail = true; + Con_Printf("PSK bone %s does not exist in PSA %s\n", boneinfo[i].name); + break; + } + } + } +/* for (i = 0; i < num_boneinfo; i++) { animbones[i].parent = LittleLong(animbones[i].parent); @@ -4644,16 +4680,16 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) if (strcmp(boneinfo[i].name, animbones[i].name)) { fail = true; - Con_Printf("PSK/PSA bone names do not match\n"); + Con_Printf("PSK/PSA bone names do not match %s vs %s\n", boneinfo[i].name, animbones[i].name); break; } - if (boneinfo[i].parent != animbones[i].parent) + else if (boneinfo[i].parent != animbones[i].parent) { fail = true; - Con_Printf("PSK/PSA bone parents do not match\n"); + Con_Printf("PSK/PSA bone parents do not match for bone %s\n", boneinfo[i].name); break; } - } + }*/ } } else if (!strcmp("ANIMINFO", chunk->id) && chunk->recordsize == sizeof(pskaniminfo_t)) @@ -4760,6 +4796,8 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) Matrix3x4_InvertTo4x4_Simple(basematrix+i*12, basematrix_inverse+i*16); } + +#ifndef PSK_GPU /*expand the translations*/ num_trans = 0; for (i = 0; i < num_vtxw; i++) @@ -4791,7 +4829,7 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) } } } - +#else skel_xyz = Hunk_Alloc(sizeof(*skel_xyz) * num_vtxw); skel_norm = Hunk_Alloc(sizeof(*skel_norm) * num_vtxw); skel_idx = Hunk_Alloc(sizeof(*skel_idx) * num_vtxw); @@ -4829,16 +4867,19 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) if (t != 1) for (j = 0; j < 4; j++) skel_weights[i][j] *= 1/t; + + + skel_xyz[i][0] = pnts[vtxw[i].pntsindex].origin[0]; + skel_xyz[i][1] = pnts[vtxw[i].pntsindex].origin[1]; + skel_xyz[i][2] = pnts[vtxw[i].pntsindex].origin[2]; } +#endif #ifndef SERVERONLY /*st coords, all share the same list*/ stcoord = Hunk_Alloc(sizeof(vec2_t)*num_vtxw); for (i = 0; i < num_vtxw; i++) { - skel_xyz[i][0] = pnts[vtxw[i].pntsindex].origin[0]; - skel_xyz[i][1] = pnts[vtxw[i].pntsindex].origin[1]; - skel_xyz[i][2] = pnts[vtxw[i].pntsindex].origin[2]; stcoord[i*2+0] = vtxw[i].texcoord[0]; stcoord[i*2+1] = vtxw[i].texcoord[1]; } @@ -4849,7 +4890,7 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) if (animinfo && animkeys) { - if (1/*dpcompat_psa_ungroup.ival*/) + if (dpcompat_psa_ungroup.ival) { /*unpack each frame of each animation to be a separate framegroup*/ unsigned int iframe; /*individual frame count*/ @@ -4886,15 +4927,20 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) Q_strncpyz(group[i].name, animinfo[i].name, sizeof(group[i].name)); group[i].loop = true; group[i].rate = animinfo[i].fps; - group[i].isheirachical = false; + group[i].isheirachical = true; } } - for (i = 0; i < num_animkeys; i++) + for (j = 0; j < num_animkeys; j += num_boneinfo) { - PSKGenMatrix( - animkeys[i].origin[0], animkeys[i].origin[1], animkeys[i].origin[2], - animkeys[i].quat[0], animkeys[i].quat[1], animkeys[i].quat[2], animkeys[i].quat[3], - animmatrix + i*12); + pskanimkeys_t *sb; + for (i = 0; i < num_boneinfo; i++) + { + sb = &animkeys[j + bonemap[i]]; + PSKGenMatrix( + sb->origin[0], sb->origin[1], sb->origin[2], + sb->quat[0], sb->quat[1], sb->quat[2], sb->quat[3], + animmatrix + (j+i)*12); + } } } else @@ -4953,14 +4999,16 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) gmdl[i].ofsbones = (char*)bones - (char*)&gmdl[i]; gmdl[i].numbones = num_boneinfo; +#ifndef PSK_GPU gmdl[i].ofsswtransforms = (char*)trans - (char*)&gmdl[i]; gmdl[i].numswtransforms = num_trans; -/* +#else gmdl[i].ofs_skel_idx = (char*)skel_idx - (char*)&gmdl[i]; gmdl[i].ofs_skel_weight = (char*)skel_weights - (char*)&gmdl[i]; gmdl[i].ofs_skel_xyz = (char*)skel_xyz - (char*)&gmdl[i]; gmdl[i].ofs_skel_norm = (char*)skel_norm - (char*)&gmdl[i]; -*/ +#endif + gmdl[i].shares_verts = 0; gmdl[i].shares_bones = 0; gmdl[i].nextsurf = (i != num_matt-1)?sizeof(*gmdl):0; diff --git a/engine/common/com_phys_ode.c b/engine/common/com_phys_ode.c index e6d1ded40..ad6ec961d 100644 --- a/engine/common/com_phys_ode.c +++ b/engine/common/com_phys_ode.c @@ -1417,7 +1417,7 @@ static void World_ODE_Frame_BodyToEntity(world_t *world, wedict_t *ed) if (ed->v->modelindex) { - model = world->GetCModel(world, ed->v->modelindex); + model = world->Get_CModel(world, ed->v->modelindex); if (!model || model->type == mod_alias) { angles[PITCH] *= -1; @@ -1776,7 +1776,7 @@ static void World_ODE_Frame_BodyFromEntity(world_t *world, wedict_t *ed) { case SOLID_BSP: modelindex = (int)ed->v->modelindex; - model = world->GetCModel(world, modelindex); + model = world->Get_CModel(world, modelindex); if (model) { VectorScale(model->mins, scale, entmins); @@ -1971,7 +1971,7 @@ static void World_ODE_Frame_BodyFromEntity(world_t *world, wedict_t *ed) if (ed->v->modelindex) { - model = world->GetCModel(world, ed->v->modelindex); + model = world->Get_CModel(world, ed->v->modelindex); if (!model || model->type == mod_alias) { qangles[PITCH] *= -1; diff --git a/engine/common/common.c b/engine/common/common.c index fe7a967e5..c75b703da 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -626,6 +626,43 @@ float Q_atof (const char *str) return val*sign; } +/* +attempts to remove leet strange chars from a name +the resulting string is not intended to be visible to humans, but this functions results can be matched against each other. +*/ +void deleetstring(char *result, char *leet) +{ + char *s = result; + char *s2 = leet; + while(*s2) + { + if (*s2 == 0xff) + { + s2++; + continue; + } + *s = *s2 & ~128; + s2++; + if (*s == '3') + *s = 'e'; + else if (*s == '4') + *s = 'a'; + else if (*s == '0') + *s = 'o'; + else if (*s == '1' || *s == '7') + *s = 'l'; + else if (*s >= 18 && *s < 27) + *s = *s - 18 + '0'; + else if (*s >= 'A' && *s <= 'Z') + *s = *s - 'A' + 'a'; + else if (*s == '_' || *s == ' ' || *s == '~') + continue; + s++; + } + *s = '\0'; +} + + /* ============================================================================ diff --git a/engine/common/common.h b/engine/common/common.h index 32fb402de..831f7be49 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -239,7 +239,7 @@ int Q_strncasecmp (const char *s1, const char *s2, int n); int Q_strcasecmp (const char *s1, const char *s2); int Q_atoi (const char *str); float Q_atof (const char *str); - +void deleetstring(char *result, char *leet); //============================================================================ @@ -321,7 +321,7 @@ struct vfsfile_s *FS_OpenReadLocation(flocation_t *location); char *FS_WhichPackForLocation(flocation_t *loc); char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly); -char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly); +char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly, qboolean ext); int COM_FOpenFile (const char *filename, FILE **file); int COM_FOpenWriteFile (const char *filename, FILE **file); @@ -390,6 +390,7 @@ qbyte *COM_LoadHunkFile (const char *path); qbyte *COM_LoadMallocFile (const char *path); void COM_LoadCacheFile (const char *path, struct cache_user_s *cu); void FS_ForceToPure(const char *str, const char *crcs, int seed); +void FS_ImpurePacks(const char *names, const char *crcs); char *COM_GetPathInfo (int i, int *crc); char *COM_NextPath (char *prevpath); void COM_FlushFSCache(void); //a file was written using fopen diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 3d47c9de0..0b4e64af4 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -751,14 +751,14 @@ qboolean Cvar_ApplyLatchFlag(cvar_t *var, char *value, int flag) var->latched_string = NULL; if (!latch) { -#ifndef _MSC_VER - #warning this means the callback will never be called +#ifdef warningmsg +#pragma warningmsg("this means the callback will never be called") #endif latch = var->string; var->string = NULL; } -#ifndef _MSC_VER -#warning set or forceset? +#ifdef warningmsg +#pragma warningmsg("set or forceset?") #endif Cvar_ForceSet(var, value); @@ -801,8 +801,8 @@ void Cvar_ForceCheatVars(qboolean semicheats, qboolean absolutecheats) var->latched_string = NULL; if (!latch) { -#ifndef _MSC_VER - #warning this means the callback will never be called +#ifdef warningmsg +#pragma warningmsg("this means the callback will never be called") #endif latch = var->string; var->string = NULL; diff --git a/engine/common/fs.c b/engine/common/fs.c index a513a712b..bd1ca8db3 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -607,7 +607,7 @@ char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly) return buffer; } } -char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly) +char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly, qboolean ext) { char temp[MAX_OSPATH]; searchpath_t *search; @@ -618,8 +618,15 @@ char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly) { for (search = com_purepaths ; search ; search = search->nextpure) { - COM_StripExtension(search->purepath, temp, sizeof(temp)); - Q_strncatz(buffer, va("%s ", temp), buffersize); + if (!ext) + { + COM_StripExtension(search->purepath, temp, sizeof(temp)); + Q_strncatz(buffer, va("%s ", temp), buffersize); + } + else + { + Q_strncatz(buffer, va("%s ", search->purepath), buffersize); + } } return buffer; } @@ -631,8 +638,15 @@ char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly) search->crc_check = search->funcs->GeneratePureCRC(search->handle, 0, 0); if (search->crc_check) { - COM_StripExtension(search->purepath, temp, sizeof(temp)); - Q_strncatz(buffer, va("%s ", temp), buffersize); + if (!ext) + { + COM_StripExtension(search->purepath, temp, sizeof(temp)); + Q_strncatz(buffer, va("%s ", temp), buffersize); + } + else + { + Q_strncatz(buffer, va("%s ", search->purepath), buffersize); + } } } return buffer; @@ -815,6 +829,7 @@ qboolean FS_NativePath(const char *fname, enum fs_relative relativeto, char *out return true; } +/*locates and opens a file*/ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative relativeto) { char cleanname[MAX_QPATH]; @@ -906,6 +921,7 @@ vfsfile_t *FS_OpenVFS(const char *filename, const char *mode, enum fs_relative r return NULL; } +/*opens a vfsfile from an already discovered location*/ vfsfile_t *FS_OpenReadLocation(flocation_t *location) { if (location->search) @@ -1138,16 +1154,24 @@ void COM_EnumerateFiles (const char *match, int (*func)(const char *, int, void void COM_FlushTempoaryPacks(void) { - searchpath_t *next; - while (com_searchpaths && com_searchpaths->istemporary) + searchpath_t *sp, **link; + link = &com_searchpaths; + while (*link) { - com_searchpaths->funcs->ClosePath(com_searchpaths->handle); - next = com_searchpaths->next; - Z_Free (com_searchpaths); - com_searchpaths = next; + sp = *link; + if (sp->istemporary) + { + FS_FlushFSHash(); - com_fschanged = true; + *link = sp->next; + + sp->funcs->ClosePath(sp->handle); + Z_Free (sp); + } + else + link = &sp->next; } + com_purepaths = NULL; } qboolean COM_LoadMapPackFile (const char *filename, int ofs) @@ -1324,7 +1348,7 @@ static searchpath_t *FS_AddPathHandle(const char *purepath, const char *probable { unsigned int i; - searchpath_t *search; + searchpath_t *search, **link; if (!funcs) { @@ -1340,19 +1364,35 @@ static searchpath_t *FS_AddPathHandle(const char *purepath, const char *probable search->funcs = funcs; Q_strncpyz(search->purepath, purepath, sizeof(search->purepath)); - search->next = com_searchpaths; - com_searchpaths = search; + if (istemporary) + { + //add at end. pureness will reorder if needed. + link = &com_searchpaths; + while(*link) + { + link = &(*link)->next; + } + *link = search; + } + else + { + search->next = com_searchpaths; + com_searchpaths = search; + } com_fschanged = true; - - for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++) + //temp packages also do not nest + if (!istemporary) { - if (!searchpathformats[i].extension || !searchpathformats[i].funcs || !searchpathformats[i].funcs->OpenNew) - continue; - if (loadstuff & (1<OpenNew) + continue; + if (loadstuff & (1<next) + { + if (!stricmp(sp->purepath, pname)) + { + break; + } + } + if (!sp) + { + char local[MAX_OSPATH]; + vfsfile_t *vfs; + char *ext = COM_FileExtension(pname); + void *handle; + int i; + + FS_GenCachedPakName(pname, va("%i", crc), local, sizeof(local)); + vfs = FS_OpenVFS(local, "rb", FS_ROOT); + if (vfs) + { + for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++) + { + if (!searchpathformats[i].extension || !searchpathformats[i].funcs || !searchpathformats[i].funcs->OpenNew) + continue; + if (!strcmp(ext, searchpathformats[i].extension)) + { + handle = searchpathformats[i].funcs->OpenNew (vfs, local); + if (!handle) + break; + sp = FS_AddPathHandle(pname, local, searchpathformats[i].funcs, handle, true, true, false, (unsigned int)-1); + + FS_FlushFSHash(); + break; + } + } + } + + if (!sp) + Con_DPrintf("Unable to load matching package file %s\n", pname); + } + } + + FS_ForceToPure(NULL, NULL, 0); +} + //space-seperate pk3 names followed by space-seperated crcs //note that we'll need to reorder and filter out files that don't match the crc. -void FS_ForceToPure(const char *str, const char *crcs, int seed) +void FS_ForceToPure(const char *names, const char *crcs, int seed) { //pure files are more important than non-pure. searchpath_t *sp; searchpath_t *lastpure = NULL; int crc; + qboolean waspure = com_purepaths != NULL; + char *pname; - if (!str) + if (!crcs || !*crcs) { //pure isn't in use. if (com_purepaths) + { Con_Printf("Pure FS deactivated\n"); - com_purepaths = NULL; - FS_FlushFSHash(); + com_purepaths = NULL; + FS_FlushFSHash(); + } return; } - if (!com_purepaths) - Con_Printf("Pure FS activated\n"); + com_purepaths = NULL; for (sp = com_searchpaths; sp; sp = sp->next) { if (sp->funcs->GeneratePureCRC) @@ -1718,6 +1848,7 @@ void FS_ForceToPure(const char *str, const char *crcs, int seed) } else { + sp->nextpure = NULL; sp->crc_check = 0; sp->crc_reply = 0; } @@ -1727,10 +1858,15 @@ void FS_ForceToPure(const char *str, const char *crcs, int seed) { crcs = COM_Parse(crcs); crc = atoi(com_token); + names = COM_Parse(names); if (!crc) continue; + pname = com_token; + if (*pname == '*') + pname++; + for (sp = com_searchpaths; sp; sp = sp->next) { if (sp->nextpure == (void*)0x1) //don't add twice. @@ -1746,23 +1882,54 @@ void FS_ForceToPure(const char *str, const char *crcs, int seed) } } if (!sp) - Con_Printf("Pure crc %i wasn't found\n", crc); - } - -/* don't add any extras. - for (sp = com_searchpaths; sp; sp = sp->next) - { - if (sp->nextpure == (void*)0x1) { - if (lastpure) - lastpure->nextpure = sp; - sp->nextpure = NULL; - lastpure = sp; + char local[MAX_OSPATH]; + vfsfile_t *vfs; + char *ext = COM_FileExtension(pname); + void *handle; + int i; + + FS_GenCachedPakName(pname, va("%i", crc), local, sizeof(local)); + vfs = FS_OpenVFS(local, "rb", FS_ROOT); + if (vfs) + { + for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++) + { + if (!searchpathformats[i].extension || !searchpathformats[i].funcs || !searchpathformats[i].funcs->OpenNew) + continue; + if (!strcmp(ext, searchpathformats[i].extension)) + { + handle = searchpathformats[i].funcs->OpenNew (vfs, local); + if (!handle) + break; + sp = FS_AddPathHandle(pname, local, searchpathformats[i].funcs, handle, true, true, false, (unsigned int)-1); + + sp->crc_check = sp->funcs->GeneratePureCRC(sp->handle, seed, 0); + sp->crc_reply = sp->funcs->GeneratePureCRC(sp->handle, seed, 1); + + if (sp->crc_check == crc) + { + if (lastpure) + lastpure->nextpure = sp; + else + com_purepaths = sp; + sp->nextpure = NULL; + lastpure = sp; + } + break; + } + } + } + + if (!sp) + Con_DPrintf("Pure crc %i wasn't found\n", crc); } } -*/ FS_FlushFSHash(); + + if (com_purepaths && !waspure) + Con_Printf("Pure FS activated\n"); } char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum) @@ -1858,6 +2025,8 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags) if (!com_base_searchpaths) com_base_searchpaths = com_searchpaths; + + /*sv_pure: Reload pure paths*/ } void FS_UnloadPackFiles(void) diff --git a/engine/common/fs_pak.c b/engine/common/fs_pak.c index 2e33669e6..2b70aa948 100644 --- a/engine/common/fs_pak.c +++ b/engine/common/fs_pak.c @@ -148,6 +148,36 @@ int FSPAK_EnumerateFiles (void *handle, const char *match, int (*func)(const cha return true; } + +int FSPAK_GeneratePureCRC(void *handle, int seed, int crctype) +{ + pack_t *pak = handle; + + int result; + int *filecrcs; + int numcrcs=0; + int i; + + filecrcs = BZ_Malloc((pak->numfiles+1)*sizeof(int)); + filecrcs[numcrcs++] = seed; + + for (i = 0; i < pak->numfiles; i++) + { + if (pak->files[i].filelen > 0) + { + filecrcs[numcrcs++] = pak->files[i].filepos ^ pak->files[i].filelen ^ QCRC_Block(pak->files[i].name, sizeof(56)); + } + } + + if (crctype) + result = Com_BlockChecksum(filecrcs, numcrcs*sizeof(int)); + else + result = Com_BlockChecksum(filecrcs+1, (numcrcs-1)*sizeof(int)); + + BZ_Free(filecrcs); + return result; +} + /* ================= COM_LoadPackFile @@ -352,7 +382,7 @@ searchpathfuncs_t packfilefuncs = { FSPAK_ReadFile, FSPAK_EnumerateFiles, FSPAK_LoadPackFile, - NULL, + FSPAK_GeneratePureCRC, FSPAK_OpenVFS }; diff --git a/engine/common/fs_zip.c b/engine/common/fs_zip.c index 3bd71fcaa..7ebfec276 100644 --- a/engine/common/fs_zip.c +++ b/engine/common/fs_zip.c @@ -427,6 +427,7 @@ int FSZIP_GeneratePureCRC(void *handle, int seed, int crctype) zipfile_t *zip = handle; unz_file_info file_info; + int result; int *filecrcs; int numcrcs=0; int i; @@ -446,9 +447,12 @@ int FSZIP_GeneratePureCRC(void *handle, int seed, int crctype) } if (crctype) - return Com_BlockChecksum(filecrcs, numcrcs*sizeof(int)); + result = Com_BlockChecksum(filecrcs, numcrcs*sizeof(int)); else - return Com_BlockChecksum(filecrcs+1, (numcrcs-1)*sizeof(int)); + result = Com_BlockChecksum(filecrcs+1, (numcrcs-1)*sizeof(int)); + + BZ_Free(filecrcs); + return result; } typedef struct { diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 5949ac96e..4fb2ea2c2 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -28,7 +28,7 @@ extern cvar_t r_shadow_bumpscale_basetexture; //these are in model.c (or gl_model.c) qboolean RMod_LoadVertexes (lump_t *l); -qboolean RMod_LoadEdges (lump_t *l); +qboolean RMod_LoadEdges (lump_t *l, qboolean lm); qboolean RMod_LoadMarksurfaces (lump_t *l); qboolean RMod_LoadSurfedges (lump_t *l); void RMod_LoadLighting (lump_t *l); @@ -1323,7 +1323,7 @@ Mod_LoadFaces #ifndef SERVERONLY qboolean CMod_LoadFaces (lump_t *l) { - dface_t *in; + dsface_t *in; msurface_t *out; int i, count, surfnum; int planenum, side; @@ -3863,7 +3863,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned // load into heap #ifndef SERVERONLY noerrors = noerrors && RMod_LoadVertexes (&header.lumps[Q2LUMP_VERTEXES]); - noerrors = noerrors && RMod_LoadEdges (&header.lumps[Q2LUMP_EDGES]); + noerrors = noerrors && RMod_LoadEdges (&header.lumps[Q2LUMP_EDGES], false); noerrors = noerrors && RMod_LoadSurfedges (&header.lumps[Q2LUMP_SURFEDGES]); if (noerrors) RMod_LoadLighting (&header.lumps[Q2LUMP_LIGHTING]); diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index dd1b09b82..3fafc8326 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -403,34 +403,9 @@ void QDECL AngleVectors (const vec3_t angles, vec3_t forward, vec3_t right, vec3 } } -void QDECL vectoangles(vec3_t vec, vec3_t ang) +void QDECL vectoangles(vec3_t fwd, vec3_t ang) { - float forward; - float yaw, pitch; - - if (vec[1] == 0 && vec[0] == 0) - { - yaw = 0; - if (vec[2] > 0) - pitch = 90; - else - pitch = 270; - } - else - { - yaw = /*(int)*/ (atan2(vec[1], vec[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; - - forward = sqrt (vec[0]*vec[0] + vec[1]*vec[1]); - pitch = /*(int)*/ (atan2(vec[2], forward) * 180 / M_PI); - if (pitch < 0) - pitch += 360; - } - - ang[0] = pitch; - ang[1] = yaw; - ang[2] = 0; + VectorAngles(fwd, NULL, ang); } int VectorCompare (const vec3_t v1, const vec3_t v2) diff --git a/engine/common/net.h b/engine/common/net.h index be8f8cffb..0fa0c28ca 100644 --- a/engine/common/net.h +++ b/engine/common/net.h @@ -78,7 +78,7 @@ void NET_InitServer (void); void NET_CloseServer (void); void UDP_CloseSocket (int socket); void NET_Shutdown (void); -qboolean NET_GetPacket (netsrc_t socket); +int NET_GetPacket (netsrc_t netsrc, int firstsock); void NET_SendPacket (netsrc_t socket, int length, void *data, netadr_t to); int NET_LocalAddressForRemote(struct ftenet_connections_s *collection, netadr_t *remote, netadr_t *local, int idx); void NET_PrintAddresses(struct ftenet_connections_s *collection); @@ -232,9 +232,20 @@ void Huff_EmitByte(int ch, qbyte *buffer, int *count); #define H2_PROTOCOL_VERSION 19 #define NEHD_PROTOCOL_VERSION 250 #define FITZ_PROTOCOL_VERSION 666 +#define RMQ_PROTOCOL_VERSION 999 #define DP5_PROTOCOL_VERSION 3502 #define DP6_PROTOCOL_VERSION 3503 #define DP7_PROTOCOL_VERSION 3504 + +/*RMQ protocol flags*/ +#define RMQFL_SHORTANGLE (1 << 1) +#define RMQFL_FLOATANGLE (1 << 2) +#define RMQFL_24BITCOORD (1 << 3) +#define RMQFL_FLOATCOORD (1 << 4) +#define RMQFL_EDICTSCALE (1 << 5) +#define RMQFL_ALPHASANITY (1 << 6) +#define RMQFL_MOREFLAGS (1 << 31) + #endif int UDP_OpenSocket (int port, qboolean bcast); diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index a7ea5ba82..76c2c8c25 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -205,6 +205,8 @@ qboolean Netchan_CanPacket (netchan_t *chan, int rate) { if (chan->remote_address.type == NA_LOOPBACK) return true; //don't ever drop packets due to possible routing problems when there is no routing. + if (!rate) + return true; if (chan->cleartime < realtime + MAX_BACKUP/(float)rate) return true; return false; @@ -212,10 +214,13 @@ qboolean Netchan_CanPacket (netchan_t *chan, int rate) void Netchan_Block (netchan_t *chan, int bytes, int rate) { - if (chan->cleartime < realtime-0.25) //0.25 allows it to be a little bursty. - chan->cleartime = realtime + bytes/(float)rate; - else - chan->cleartime += bytes/(float)rate; + if (rate) + { + if (chan->cleartime < realtime-0.25) //0.25 allows it to be a little bursty. + chan->cleartime = realtime + bytes/(float)rate; + else + chan->cleartime += bytes/(float)rate; + } } @@ -275,6 +280,13 @@ nqprot_t NQNetChan_Process(netchan_t *chan) else if (sequence > chan->reliable_sequence) Con_Printf("Future ack recieved\n"); + if (showpackets.value) + Con_Printf ("<-- a s=%i a=%i(%i) %i\n" + , chan->outgoing_sequence + , chan->incoming_sequence + , chan->incoming_reliable_sequence + , 0); + return NQP_ERROR; //don't try execing the 'payload'. I hate ack packets. } @@ -297,6 +309,13 @@ nqprot_t NQNetChan_Process(netchan_t *chan) chan->incoming_acknowledged++; chan->good_count++; + + if (showpackets.value) + Con_Printf ("<-- u s=%i a=%i(%i) %i\n" + , chan->outgoing_sequence + , chan->incoming_sequence + , chan->incoming_reliable_sequence + , net_message.cursize); return NQP_DATAGRAM; } if (header & NETFLAG_DATA) @@ -327,11 +346,19 @@ nqprot_t NQNetChan_Process(netchan_t *chan) SZ_Write(&net_message, chan->in_fragment_buf, chan->in_fragment_length); chan->in_fragment_length = 0; MSG_BeginReading(chan->netprim); + + if (showpackets.value) + Con_Printf ("<-- r s=%i a=%i(%i) %i\n" + , chan->outgoing_sequence + , chan->incoming_sequence + , chan->incoming_reliable_sequence + , net_message.cursize); return NQP_RELIABLE; //we can read it now } } else Con_DPrintf("Stale reliable (%i)\n", sequence); + return NQP_ERROR; } diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index c54c559e5..6a4017b70 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -23,10 +23,7 @@ struct sockaddr; #include "quakedef.h" #include "netinc.h" -#ifdef _MSC_VER -#pragma message("these two are never set. A NET_ReplySource function that returns the address a reply would originate from would be sufficient. Note that INADDR_ANY can be multiple however, so these are just a hint.") -#endif -netadr_t net_local_cl_ipadr; //still used to match local ui requests, and to generate ip reports for q3 servers. +netadr_t net_local_cl_ipadr; //still used to match local ui requests (quake/gamespy), and to generate ip reports for q3 servers (which is probably pointless). netadr_t net_from; sizebuf_t net_message; @@ -64,7 +61,7 @@ void (*pfreeaddrinfo) (struct addrinfo*); void NET_GetLocalAddress (int socket, netadr_t *out); int TCP_OpenListenSocket (int port); -extern cvar_t sv_port; +extern cvar_t sv_port_ipv4; #ifdef IPPROTO_IPV6 int UDP6_OpenSocket (int port, qboolean bcast); extern cvar_t sv_port_ipv6; @@ -1024,26 +1021,22 @@ qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask) // check to make sure all types match if (a.type != b.type) { - if (a.type == NA_IP && b.type == NA_IPV6) + if (a.type == NA_IP && b.type == NA_IPV6 && mask.type == NA_IP) { -#ifndef _MSC_VER -#warning code me -#endif - //okay, comparing an ipv4 address against an ipv4-as-6 - /* for (i = 0; i < 10; i++) - if (mask.address.ip[i] != 0) - return false; - + for (i = 0; i < 10; i++) + if (b.address.ip6[i] != 0) + return false; //only matches if they're 0s, otherwise its not an ipv4 address there for (; i < 12; i++) + if (b.address.ip6[i] != 0xff && b.address.ip6[i] != 0x00) //0x00 is depricated + return false; //only matches if they're 0s or ffs, otherwise its not an ipv4 address there + for (i = 0; i < 4; i++) { - if (mask.address.ip[i] != 0xff) + if ((a.address.ip[i] & mask.address.ip[i]) != (b.address.ip6[12+i] & mask.address.ip[i])) + return false; //mask doesn't match } - if (i == 12) - { - - }*/ + return true; //its an ipv4 address in there, the mask matched the whole way through } - if (a.type == NA_IPV6 && b.type == NA_IP) + if (a.type == NA_IPV6 && b.type == NA_IP && mask.type == NA_IP) { for (i = 0; i < 10; i++) if (a.address.ip6[i] != 0) @@ -1696,6 +1689,7 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i int family; int port; int bindtries; + int bufsz; if (!NET_PortToAdr(adrfamily, address, &adr)) @@ -1711,6 +1705,9 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i return NULL; } + bufsz = 1<<18; + setsockopt(newsocket, SOL_SOCKET, SO_RCVBUF, (void*)&bufsz, sizeof(bufsz)); + //try and find an unused port. port = ntohs(((struct sockaddr_in*)&qs)->sin_port); for (bindtries = 100; bindtries > 0; bindtries--) @@ -1735,6 +1732,13 @@ ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, i if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(qerrno)); + + // + // determine my name & address if we don't already know it + // + if (!net_local_cl_ipadr.type == NA_INVALID) + NET_GetLocalAddress (newsocket, &net_local_cl_ipadr); + newcon = Z_Malloc(sizeof(*newcon)); if (newcon) { @@ -2669,9 +2673,9 @@ struct ftenet_generic_connection_s *FTENET_IRCConnect_EstablishConnection(qboole #endif -qboolean NET_GetPacket (netsrc_t netsrc) +/*firstsock is a cookie*/ +int NET_GetPacket (netsrc_t netsrc, int firstsock) { - int i; ftenet_connections_t *collection; if (netsrc == NS_SERVER) { @@ -2693,20 +2697,20 @@ qboolean NET_GetPacket (netsrc_t netsrc) } if (!collection) - return false; + return -1; - for (i = 0; i < MAX_CONNECTIONS; i++) + for (; firstsock < MAX_CONNECTIONS; firstsock+=1) { - if (!collection->conn[i]) + if (!collection->conn[firstsock]) break; - if (collection->conn[i]->GetPacket(collection->conn[i])) + if (collection->conn[firstsock]->GetPacket(collection->conn[firstsock])) { - net_from.connum = i+1; - return true; + net_from.connum = firstsock+1; + return firstsock; } } - return false; + return -1; } int NET_LocalAddressForRemote(ftenet_connections_t *collection, netadr_t *remote, netadr_t *local, int idx) @@ -3314,11 +3318,6 @@ void NET_InitClient(void) net_message.maxsize = sizeof(net_message_buffer); net_message.data = net_message_buffer; - // - // determine my name & address - // -// NET_GetLocalAddress (cls.socketip, &net_local_cl_ipadr); - Con_TPrintf(TL_CLIENTPORTINITED); } #endif @@ -3381,7 +3380,7 @@ void NET_InitServer(void) allowconnects = true; - Cvar_ForceCallback(&sv_port); + Cvar_ForceCallback(&sv_port_ipv4); #ifdef IPPROTO_IPV6 Cvar_ForceCallback(&sv_port_ipv6); #endif diff --git a/engine/common/particles.h b/engine/common/particles.h index fae9ac900..f61e5cf5e 100644 --- a/engine/common/particles.h +++ b/engine/common/particles.h @@ -128,7 +128,7 @@ typedef struct { int (*FindParticleType) (char *name); int (*RunParticleEffectTypeString) (vec3_t org, vec3_t dir, float count, char *name); - int (*ParticleTrail) (vec3_t startpos, vec3_t end, int type, trailstate_t **tsk); + int (*ParticleTrail) (vec3_t startpos, vec3_t end, int type, int dlkey, trailstate_t **tsk); int (*RunParticleEffectState) (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk); void (*RunParticleWeather) (vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, char *efname); void (*RunParticleCube) (vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, qboolean gravity, float jitter); diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index e10351006..fe804e392 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -1059,6 +1059,7 @@ void QCBUILTIN PF_Spawn (progfuncs_t *prinst, struct globalvars_s *pr_globals) { struct edict_s *ed; ed = ED_Alloc(prinst); + pr_globals = PR_globals(prinst, PR_CURRENT); RETURN_EDICT(prinst, ed); } @@ -2394,7 +2395,6 @@ void QCBUILTIN PF_vlen (progfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_vectoangles (progfuncs_t *prinst, struct globalvars_s *pr_globals) { float *value1, *up; - float yaw, pitch, roll; value1 = G_VECTOR(OFS_PARM0); if (*prinst->callargc >= 2) @@ -2402,56 +2402,7 @@ void QCBUILTIN PF_vectoangles (progfuncs_t *prinst, struct globalvars_s *pr_glob else up = NULL; - - - if (value1[1] == 0 && value1[0] == 0) - { - if (value1[2] > 0) - { - pitch = -M_PI*0.5; - yaw = up ? atan2(-up[1], -up[0]) : 0; - } - else - { - pitch = M_PI*0.5; - yaw = up ? atan2(up[1], up[0]) : 0; - } - roll = 0; - } - else - { - yaw = atan2(value1[1], value1[0]); - pitch = -atan2(value1[2], sqrt (value1[0]*value1[0] + value1[1]*value1[1])); - - if (up) - { - vec_t cp = cos(pitch), sp = sin(pitch); - vec_t cy = cos(yaw), sy = sin(yaw); - vec3_t tleft, tup; - tleft[0] = -sy; - tleft[1] = cy; - tleft[2] = 0; - tup[0] = sp*cy; - tup[1] = sp*sy; - tup[2] = cp; - roll = -atan2(DotProduct(up, tleft), DotProduct(up, tup)); - } - else - roll = 0; - } - - pitch *= -180 / M_PI; - yaw *= 180 / M_PI; - roll *= 180 / M_PI; - if (pitch < 0) - pitch += 360; - if (yaw < 0) - yaw += 360; - if (roll < 0) - roll += 360; - G_FLOAT(OFS_RETURN+0) = pitch; - G_FLOAT(OFS_RETURN+1) = yaw; - G_FLOAT(OFS_RETURN+2) = roll; + VectorAngles(value1, up, G_VECTOR(OFS_RETURN)); } //vector normalize(vector) diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index e6bf1ae29..2b7edf622 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -176,9 +176,22 @@ void PR_AutoCvar(progfuncs_t *prinst, cvar_t *var); - - - +void QCBUILTIN PF_skel_create (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skel_build (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skel_get_numbones (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skel_get_bonename (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skel_get_boneparent (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skel_find_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skel_get_bonerel (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skel_get_boneabs (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skel_set_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skel_mul_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skel_mul_bones (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skel_copybones (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_skel_delete (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void skel_lookup(progfuncs_t *prinst, int skelidx, framestate_t *out); +void skel_dodelete(progfuncs_t *prinst); +void skel_reset(progfuncs_t *prinst); //pr_cmds.c builtins that need to be moved to a common. void VARGS PR_BIError(progfuncs_t *progfuncs, char *format, ...) LIKEPRINTF(2); diff --git a/engine/common/protocol.h b/engine/common/protocol.h index d4886f2d2..d910cca88 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -736,11 +736,11 @@ typedef struct entity_state_s { unsigned short number; // edict index unsigned short modelindex; - int bitmask; // for dp ents, so lost state can be repeated in replacement packets. + unsigned int bitmask; // for dp ents, so lost state can be repeated in replacement packets. - int flags; // nolerp, etc + unsigned int flags; // nolerp, etc - int effects; + unsigned int effects; vec3_t origin; vec3_t angles; diff --git a/engine/common/world.h b/engine/common/world.h index 730fcafc6..d9fb1d8e3 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -122,7 +122,8 @@ struct world_s void (*Event_Touch)(struct world_s *w, wedict_t *s, wedict_t *o); void (*Event_Think)(struct world_s *w, wedict_t *s); void (*Event_Sound) (wedict_t *entity, int channel, char *sample, int volume, float attenuation, int pitchadj); - model_t *(*GetCModel)(struct world_s *w, int modelindex); + model_t *(*Get_CModel)(struct world_s *w, int modelindex); + void (*Get_FrameState)(struct world_s *w, wedict_t *s, framestate_t *fstate); unsigned int max_edicts; //limiting factor... 1024 fields*4*MAX_EDICTS == a heck of a lot. unsigned int num_edicts; // increases towards MAX_EDICTS @@ -149,6 +150,10 @@ struct world_s float *time; float *frametime; float *force_retouch; + float *physics_mode; + float *v_forward; + float *v_right; + float *v_up; } g; #ifdef USEODE diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index 07ea1a74b..0700890ce 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -1,5 +1,6 @@ #include "quakedef.h" #include "glquake.h" +#include "gl_draw.h" #ifdef D3DQUAKE #include "shader.h" #if !defined(HMONITOR_DECLARED) && (WINVER < 0x0500) @@ -523,6 +524,8 @@ void D3DBE_Init(void) shaderstate.dynidx_size = sizeof(index_t) * DYNIBUFFSIZE; D3DBE_Reset(false); + + R_InitFlashblends(); } static void allocvertexbuffer(IDirect3DVertexBuffer9 *buff, unsigned int bmaxsize, unsigned int *offset, void **data, unsigned int bytes) @@ -744,15 +747,15 @@ static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *src, b ((D3DCOLOR*)dst)[cnt] = block; } break; - case RGB_GEN_VERTEX: - case RGB_GEN_EXACT_VERTEX: + case RGB_GEN_VERTEX_LIGHTING: + case RGB_GEN_VERTEX_EXACT: if (!src) { while((cnt)--) { - dst[cnt][0] = 255;//shaderstate.identitylighting; - dst[cnt][1] = 255;//shaderstate.identitylighting; - dst[cnt][2] = 255;//shaderstate.identitylighting; + dst[cnt][0] = 255; + dst[cnt][1] = 255; + dst[cnt][2] = 255; } } else @@ -839,8 +842,8 @@ static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *src, b case RGB_GEN_TOPCOLOR: case RGB_GEN_BOTTOMCOLOR: -#ifdef _MSC_VER -#pragma message("fix 24bit player colours") +#ifdef warningmsg +#pragma warningmsg("fix 24bit player colours") #endif block = D3DCOLOR_RGBA(255, 255, 255, 255); while((cnt)--) @@ -999,8 +1002,8 @@ static unsigned int BE_GenerateColourMods(unsigned int vertcount, const shaderpa } } else if (m->colors4f_array && - ((pass->rgbgen == RGB_GEN_VERTEX) || - (pass->rgbgen == RGB_GEN_EXACT_VERTEX) || + ((pass->rgbgen == RGB_GEN_VERTEX_LIGHTING) || + (pass->rgbgen == RGB_GEN_VERTEX_EXACT) || (pass->rgbgen == RGB_GEN_ONE_MINUS_VERTEX) || (pass->alphagen == ALPHA_GEN_VERTEX))) { @@ -2060,27 +2063,30 @@ void BE_UploadLightmaps(qboolean force) RECT rect; glRect_t *theRect = &lightmap[i]->rectchange; int r; - if (tex) + if (!tex) { - lightmap[i]->modified = 0; - rect.left = theRect->l; - rect.right = theRect->l + theRect->w; - rect.top = theRect->t; - rect.bottom = theRect->t + theRect->h; - - IDirect3DTexture9_LockRect(tex, 0, &lock, &rect, 0); - for (r = 0; r < lightmap[i]->rectchange.h; r++) - { - memcpy((char*)lock.pBits + r*lock.Pitch, lightmap[i]->lightmaps+(theRect->l+((r+theRect->t)*LMBLOCK_WIDTH))*lightmap_bytes, lightmap[i]->rectchange.w*lightmap_bytes); - } - IDirect3DTexture9_UnlockRect(tex, 0); - theRect->l = LMBLOCK_WIDTH; - theRect->t = LMBLOCK_HEIGHT; - theRect->h = 0; - theRect->w = 0; + lightmap_textures[i] = R_AllocNewTexture("***lightmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT); + tex = lightmap_textures[i].ptr; + if (!tex) + continue; } - else - lightmap_textures[i] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); + + lightmap[i]->modified = 0; + rect.left = theRect->l; + rect.right = theRect->l + theRect->w; + rect.top = theRect->t; + rect.bottom = theRect->t + theRect->h; + + IDirect3DTexture9_LockRect(tex, 0, &lock, &rect, 0); + for (r = 0; r < lightmap[i]->rectchange.h; r++) + { + memcpy((char*)lock.pBits + r*lock.Pitch, lightmap[i]->lightmaps+(theRect->l+((r+theRect->t)*LMBLOCK_WIDTH))*lightmap_bytes, lightmap[i]->rectchange.w*lightmap_bytes); + } + IDirect3DTexture9_UnlockRect(tex, 0); + theRect->l = LMBLOCK_WIDTH; + theRect->t = LMBLOCK_HEIGHT; + theRect->h = 0; + theRect->w = 0; } } } @@ -2656,7 +2662,7 @@ void D3DBE_DrawWorld (qbyte *vis) RSpeedEnd(RSPEED_DRAWENTITIES); } - GLR_RenderDlights (); + R_RenderDlights (); BE_RotateForEntity(&r_worldentity, NULL); } diff --git a/engine/d3d/d3d_image.c b/engine/d3d/d3d_image.c index 4ecebcf73..393279f58 100644 --- a/engine/d3d/d3d_image.c +++ b/engine/d3d/d3d_image.c @@ -9,33 +9,39 @@ extern LPDIRECT3DDEVICE9 pD3DDev9; typedef struct d3dtexture_s { + texcom_t com; struct d3dtexture_s *next; texid_t tex; - qboolean loaded; char name[1]; } d3dtexture_t; static d3dtexture_t *d3dtextures; +void D3D_Image_Shutdown(void) +{ + LPDIRECT3DTEXTURE9 tx; + while(d3dtextures) + { + d3dtexture_t *t = d3dtextures; + d3dtextures = t->next; + + tx = t->tex.ptr; + if (tx) + IDirect3DTexture9_Release(tx); + } +} + static d3dtexture_t *d3d_lookup_texture(char *ident) { d3dtexture_t *tex; - if (ident && *ident) - { - for (tex = d3dtextures; tex; tex = tex->next) - if (!strcmp(tex->name, ident)) - return tex; + for (tex = d3dtextures; tex; tex = tex->next) + if (!strcmp(tex->name, ident)) + return tex; - tex = malloc(sizeof(*tex)+strlen(ident)); - strcpy(tex->name, ident); - } - else - { - tex = malloc(sizeof(*tex)); - tex->name[0] = '\0'; - } - tex->loaded = false; + tex = calloc(1, sizeof(*tex)+strlen(ident)); + strcpy(tex->name, ident); tex->tex.ptr = NULL; + tex->tex.ref = &tex->com; tex->next = d3dtextures; d3dtextures = tex; @@ -45,7 +51,7 @@ static d3dtexture_t *d3d_lookup_texture(char *ident) extern cvar_t gl_picmip; extern cvar_t gl_picmip2d; -texid_t D3D9_AllocNewTexture(int width, int height) +texid_t D3D9_AllocNewTexture(char *ident, int width, int height) { IDirect3DTexture9 *tx; texid_t ret = r_nulltex; @@ -57,7 +63,8 @@ texid_t D3D9_AllocNewTexture(int width, int height) void D3D9_DestroyTexture (texid_t tex) { IDirect3DTexture9 *tx = tex.ptr; - IDirect3DTexture9_Release(tx); + if (tx) + IDirect3DTexture9_Release(tx); } static void D3D9_RoundDimensions(int *scaled_width, int *scaled_height, qboolean mipmap) @@ -197,11 +204,10 @@ static void Upload_Texture_32(LPDIRECT3DTEXTURE9 tex, unsigned int *data, int wi } //create a basic shader from a 32bit image -static LPDIRECT3DBASETEXTURE9 D3D9_LoadTexture_32(d3dtexture_t *tex, unsigned int *data, int width, int height, int flags) +static void D3D9_LoadTexture_32(d3dtexture_t *tex, unsigned int *data, int width, int height, int flags) { int nwidth, nheight; - LPDIRECT3DTEXTURE9 newsurf; /* if (!(flags & TF_MANDATORY)) { @@ -214,21 +220,19 @@ static LPDIRECT3DBASETEXTURE9 D3D9_LoadTexture_32(d3dtexture_t *tex, unsigned in nheight = height; D3D9_RoundDimensions(&nwidth, &nheight, !(flags & IF_NOMIPMAP)); - newsurf = tex->tex.ptr; - if (!newsurf) + if (!tex->tex.ptr) + { + LPDIRECT3DTEXTURE9 newsurf; IDirect3DDevice9_CreateTexture(pD3DDev9, nwidth, nheight, (flags & IF_NOMIPMAP)?1:0, ((flags & IF_NOMIPMAP)?0:D3DUSAGE_AUTOGENMIPMAP), D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &newsurf, NULL); + if (!newsurf) + return; + tex->tex.ptr = newsurf; + } - if (!newsurf) - return NULL; - - Upload_Texture_32(newsurf, data, width, height, flags); - - tex->loaded = true; - - return (LPDIRECT3DBASETEXTURE9)newsurf; + Upload_Texture_32(tex->tex.ptr, data, width, height, flags); } -static LPDIRECT3DBASETEXTURE9 D3D9_LoadTexture_8(d3dtexture_t *tex, unsigned char *data, unsigned int *pal32, int width, int height, int flags, enum uploadfmt fmt) +static void D3D9_LoadTexture_8(d3dtexture_t *tex, unsigned char *data, unsigned int *pal32, int width, int height, int flags, enum uploadfmt fmt) { static unsigned trans[1024*1024]; int i, s; @@ -331,7 +335,7 @@ static LPDIRECT3DBASETEXTURE9 D3D9_LoadTexture_8(d3dtexture_t *tex, unsigned cha trans[i] = pal32[data[i]]; } } - return D3D9_LoadTexture_32(tex, trans, width, height, flags); + D3D9_LoadTexture_32(tex, trans, width, height, flags); } void D3D9_Upload (texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags) @@ -352,7 +356,6 @@ void D3D9_Upload (texid_t tex, char *name, enum uploadfmt fmt, void *data, vo texid_t D3D9_LoadTexture (char *identifier, int width, int height, enum uploadfmt fmt, void *data, unsigned int flags) { - texid_t tid; d3dtexture_t *tex; switch (fmt) { @@ -399,13 +402,13 @@ texid_t D3D9_LoadTexture (char *identifier, int width, int height, enum uploadfm case TF_H2_TRANS8_0: case TF_H2_T4A4: case TF_TRANS8_FULLBRIGHT: - tid.ptr = D3D9_LoadTexture_8(tex, data, d_8to24rgbtable, width, height, flags, fmt); - return tid; + D3D9_LoadTexture_8(tex, data, d_8to24rgbtable, width, height, flags, fmt); + return tex->tex; case TF_RGBX32: flags |= IF_NOALPHA; case TF_RGBA32: - tid.ptr = D3D9_LoadTexture_32(tex, data, width, height, flags); - return tid; + D3D9_LoadTexture_32(tex, data, width, height, flags); + return tex->tex; default: OutputDebugString(va("D3D_LoadTexture doesn't support fmt %i", fmt)); return r_nulltex; @@ -420,13 +423,15 @@ texid_t D3D9_LoadCompressed (char *name) texid_t D3D9_FindTexture (char *identifier) { d3dtexture_t *tex = d3d_lookup_texture(identifier); - return tex->tex; + if (tex->tex.ptr) + return tex->tex; + return r_nulltex; } texid_t D3D9_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags) { d3dtexture_t *tex = d3d_lookup_texture(identifier); - tex->tex.ptr = D3D9_LoadTexture_8(tex, data, (unsigned int *)palette32, width, height, flags, TF_SOLID8); + D3D9_LoadTexture_8(tex, data, (unsigned int *)palette32, width, height, flags, TF_SOLID8); return tex->tex; } texid_t D3D9_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags) diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index e8434a1af..35e79882c 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -50,9 +50,6 @@ #define WM_INPUT 255 #endif - -int gl_bumpmappingpossible; - //static void D3D9_GetBufferSize(int *width, int *height); //not defined static void resetD3D9(void); static LPDIRECT3D9 pD3D; @@ -1082,8 +1079,8 @@ static void (D3D9_SCR_UpdateScreen) (void) RSpeedEnd(RSPEED_TOTALREFRESH); RSpeedShow(); -#ifdef _MSC_VER -#pragma message("Fixme: ... to here") +#ifdef warningmsg +#pragma warningmsg("Fixme: ... to here") #endif @@ -1119,6 +1116,8 @@ static void (D3D9_R_Init) (void) static void (D3D9_R_DeInit) (void) { Surf_DeInit(); + Shader_Shutdown(); + D3D_Image_Shutdown(); } @@ -1297,6 +1296,7 @@ rendererinfo_t d3drendererinfo = D3DBE_ClearVBO, D3DBE_UploadAllLightmaps, NULL, + NULL, D3DBE_LightCullModel, "no more" diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index a83c20cdd..f8d0831d7 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -666,7 +666,8 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../libs/speex,..\client,../libs/freetype2/include,../common,../server,../gl,../sw,../qclib,../libs,../libs/dxsdk7/include" - PreprocessorDefinitions="_DEBUG;GLQUAKE;WIN32;_WINDOWS;MULTITHREAD" + PreprocessorDefinitions="_DEBUG;GLQUAKE;WIN32;_WINDOWS;MULTITHREAD;BOTLIB_STATIC" + BasicRuntimeChecks="3" RuntimeLibrary="1" EnableFunctionLevelLinking="true" FloatingPointModel="2" @@ -1984,6 +1985,7 @@ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" + WholeProgramOptimization="1" > + + @@ -16397,4354 +16404,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -33515,6 +29174,4354 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -11112,6 +11127,10 @@ /> + + diff --git a/engine/ftequake/npapi.def b/engine/ftequake/npapi.def index 6e20462eb..e7a0cbbde 100644 --- a/engine/ftequake/npapi.def +++ b/engine/ftequake/npapi.def @@ -1,7 +1,17 @@ +LIBRARY npfte.dll + EXPORTS +;npapi NP_GetEntryPoints NP_GetMIMEDescription NP_Initialize NP_Shutdown +;activex + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE + +;fte-specific Plug_GetFuncs \ No newline at end of file diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index bff151f90..9ff8cb12a 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -514,12 +514,12 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, } if (qrenderer == QR_OPENGL) { - texnums->base = R_AllocNewTexture(scaled_width, scaled_height); - R_Upload(texnums->base, "", h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); + texnums->base = R_AllocNewTexture(cm->name, scaled_width, scaled_height); + R_Upload(texnums->base, cm->name, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); } else { - texnums->base = R_LoadTexture(NULL, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, 0); + texnums->base = R_LoadTexture(cm->name, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, 0); } if (!h2playertranslations) @@ -540,12 +540,12 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, } if (qrenderer == QR_OPENGL) { - texnums->fullbright = R_AllocNewTexture(scaled_width, scaled_height); - R_Upload(texnums->fullbright, "", TF_RGBA32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); + texnums->fullbright = R_AllocNewTexture(cm->name, scaled_width, scaled_height); + R_Upload(texnums->fullbright, cm->name, TF_RGBA32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); } else { - texnums->fullbright = R_LoadTexture(NULL, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, 0); + texnums->fullbright = R_LoadTexture(cm->name, scaled_width, scaled_height, h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, 0); } } } @@ -783,7 +783,8 @@ static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel) dist); add = cl_dlights[i].radius - Length(dist); - if (add > 0) { + if (add > 0) + { add*=5; ambientlight[0] += add * cl_dlights[i].color[0]; ambientlight[1] += add * cl_dlights[i].color[1]; @@ -853,7 +854,7 @@ static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel) ambientlight[i] /= 200.0/255; } - if ((e->model->flags & EF_ROTATE) && cl.hexen2pickups) + if ((e->model->flags & MF_ROTATE) && cl.hexen2pickups) { shadelight[0] = shadelight[1] = shadelight[2] = ambientlight[0] = ambientlight[1] = ambientlight[2] = 128+sin(cl.servertime*4)*64; diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index c4aefb788..6a3dad503 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -4,7 +4,7 @@ //FIXME: this shouldn't be defined #define FORCESTATE #else -//#define FORCESTATE +#define FORCESTATE #endif //#define WIREFRAME @@ -34,37 +34,35 @@ uniform mat4 entmatrix;\n\ #define LIGHTPASS_GLSL_VERTEX "\ #ifdef VERTEX_SHADER\n\ +#include \"sys/skeletal.h\"\n\ \ uniform vec3 l_lightposition;\n\ +attribute vec2 v_texcoord;\n\ \ #if defined(SPECULAR) || defined(OFFSETMAPPING)\n\ -uniform vec3 eyeposition;\n\ +uniform vec3 e_eyepos;\n\ #endif\n\ \ -attribute vec2 v_texcoord;\n\ -attribute vec3 v_normal;\n\ -attribute vec3 v_svector;\n\ -attribute vec3 v_tvector;\n\ -\ -void main (void)\n\ +void main ()\n\ {\n\ - gl_Position = ftetransform();\n\ + vec3 n, s, t, w;\n\ + gl_Position = skeletaltransform_wnst(w,n,s,t);\n\ \ tcbase = v_texcoord; //pass the texture coords straight through\n\ \ - vec3 lightminusvertex = l_lightposition - v_position.xyz;\n\ - lightvector.x = dot(lightminusvertex, v_svector.xyz);\n\ - lightvector.y = dot(lightminusvertex, v_tvector.xyz);\n\ - lightvector.z = dot(lightminusvertex, v_normal.xyz);\n\ + vec3 lightminusvertex = l_lightposition - w.xyz;\n\ + lightvector.x = dot(lightminusvertex, s.xyz);\n\ + lightvector.y = dot(lightminusvertex, t.xyz);\n\ + lightvector.z = dot(lightminusvertex, n.xyz);\n\ \ #if defined(SPECULAR)||defined(OFFSETMAPPING)\n\ - vec3 eyeminusvertex = eyeposition - v_position.xyz;\n\ - eyevector.x = dot(eyeminusvertex, v_svector.xyz);\n\ - eyevector.y = -dot(eyeminusvertex, v_tvector.xyz);\n\ - eyevector.z = dot(eyeminusvertex, v_normal.xyz);\n\ + vec3 eyeminusvertex = e_eyepos - w.xyz;\n\ + eyevector.x = dot(eyeminusvertex, s.xyz);\n\ + eyevector.y = -dot(eyeminusvertex, t.xyz);\n\ + eyevector.z = dot(eyeminusvertex, n.xyz);\n\ #endif\n\ #if defined(PCF) || defined(SPOT) || defined(PROJECTION)\n\ - vshadowcoord = gl_TextureMatrix[7] * (entmatrix*vec4(v_position.xyz, 1.0));\n\ + vshadowcoord = gl_TextureMatrix[7] * (entmatrix*vec4(w.xyz, 1.0));\n\ #endif\n\ }\n\ #endif\n\ @@ -76,25 +74,25 @@ void main (void)\n\ float xPixelOffset = (1.0+shadowcoord.b/l_lightradius)/texx;\ float yPixelOffset = (1.0+shadowcoord.b/l_lightradius)/texy;\ float s = 0.0;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ \ - s += "f"Proj(shadowmap, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ \ - s += "f"Proj(shadowmap, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ \ - s += "f"Proj(shadowmap, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ \ colorscale *= s/5.0;\n\ " @@ -105,17 +103,17 @@ void main (void)\n\ const float xPixelOffset = 1.0/texx;\ const float yPixelOffset = 1.0/texy;\ float s = 0.0;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ \ - s += "f"Proj(shadowmap, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ \ - s += "f"Proj(shadowmap, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ colorscale *= s/9.0;\n\ " @@ -125,11 +123,11 @@ void main (void)\n\ float xPixelOffset = 1.0/texx;\ float yPixelOffset = 1.0/texy;\ float s = 0.0;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(shadowmap, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ + s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ colorscale *= s/5.0;\n\ " @@ -139,21 +137,21 @@ void main (void)\n\ #define LIGHTPASS_GLSL_FRAGMENT "\ #ifdef FRAGMENT_SHADER\n\ -uniform sampler2D baset;\n\ +uniform sampler2D s_t0;\n"/*base texture*/"\ #if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)\n\ -uniform sampler2D bumpt;\n\ +uniform sampler2D s_t1;\n"/*normalmap/height texture*/"\ #endif\n\ #ifdef SPECULAR\n\ -uniform sampler2D speculart;\n\ +uniform sampler2D s_t2;\n"/*specularmap texture*/"\ #endif\n\ #ifdef PROJECTION\n\ -uniform sampler2D projected;\n\ +uniform sampler2D s_t3;\n"/*projected texture*/"\ #endif\n\ #ifdef PCF\n\ #ifdef CUBE\n\ -uniform samplerCubeShadow shadowmap;\n\ +uniform samplerCubeShadow s_t7;\n\ #else\n\ -uniform sampler2DShadow shadowmap;\n\ +uniform sampler2DShadow s_t7;\n\ #endif\n\ #endif\n\ \ @@ -166,7 +164,7 @@ uniform float offsetmapping_scale;\n\ #endif\n\ \ \ -void main (void)\n\ +void main ()\n\ {\n\ #ifdef OFFSETMAPPING\n\ vec2 OffsetVector = normalize(eyevector).xy * offsetmapping_scale * vec2(1, -1);\n\ @@ -174,22 +172,22 @@ void main (void)\n\ #define tcbase foo\n\ tcbase += OffsetVector;\n\ OffsetVector *= 0.333;\n\ - tcbase -= OffsetVector * texture2D(bumpt, tcbase).w;\n\ - tcbase -= OffsetVector * texture2D(bumpt, tcbase).w;\n\ - tcbase -= OffsetVector * texture2D(bumpt, tcbase).w;\n\ + tcbase -= OffsetVector * texture2D(s_t1, tcbase).w;\n\ + tcbase -= OffsetVector * texture2D(s_t1, tcbase).w;\n\ + tcbase -= OffsetVector * texture2D(s_t1, tcbase).w;\n\ #endif\n\ \ \ #ifdef BUMP\n\ - vec3 bases = vec3(texture2D(baset, tcbase));\n\ + vec3 bases = vec3(texture2D(s_t0, tcbase));\n\ #else\n\ - vec3 diff = vec3(texture2D(baset, tcbase));\n\ + vec3 diff = vec3(texture2D(s_t0, tcbase));\n\ #endif\n\ #if defined(BUMP) || defined(SPECULAR)\n\ - vec3 bumps = vec3(texture2D(bumpt, tcbase)) * 2.0 - 1.0;\n\ + vec3 bumps = vec3(texture2D(s_t1, tcbase)) * 2.0 - 1.0;\n\ #endif\n\ #ifdef SPECULAR\n\ - vec3 specs = vec3(texture2D(speculart, tcbase));\n\ + vec3 specs = vec3(texture2D(s_t2, tcbase));\n\ #endif\n\ \ vec3 nl = normalize(lightvector);\n\ @@ -229,7 +227,7 @@ if (shadowcoord.w < 0.0) discard;\n\ vec2 spot = ((shadowcoord.st)/shadowcoord.w - 0.5)*2.0;colorscale*=1.0-(dot(spot,spot));\n\ #endif\n\ #if defined(PROJECTION)\n\ - l_lightcolour *= texture2d(projected, shadowcoord);\n\ + l_lightcolour *= texture2d(s_t3, shadowcoord);\n\ #endif\n\ \n\ gl_FragColor.rgb = diff*colorscale*l_lightcolour;\n\ @@ -257,33 +255,19 @@ static const char LIGHTPASS_SHADER[] = "\ #define LIGHTPASS\n\ %s\n\ }\n\ -\ - //incoming fragment\n\ - param texture 0 baset\n\ - param opt texture 1 bumpt\n\ - param opt texture 2 speculart\n\ \ param opt cvarf r_glsl_offsetmapping_bias offsetmapping_bias\n\ param opt cvarf r_glsl_offsetmapping_scale offsetmapping_scale\n\ -\ - //eye pos\n\ - param opt eyepos eyeposition\n\ \ {\n\ map $diffuse\n\ blendfunc add\n\ - tcgen base\n\ }\n\ {\n\ map $normalmap\n\ - tcgen normal\n\ }\n\ {\n\ map $specular\n\ - tcgen svector\n\ - }\n\ - {\n\ - tcgen tvector\n\ }\n\ }"; static const char PCFPASS_SHADER[] = "\ @@ -297,33 +281,24 @@ static const char PCFPASS_SHADER[] = "\ }\n\ \ //incoming fragment\n\ - param texture 7 shadowmap\n\ - param texture 1 baset\n\ - param opt texture 2 bumpt\n\ - param opt texture 3 speculart\n\ \ param opt cvarf r_glsl_offsetmapping_scale offsetmapping_scale\n\ \ //eye pos\n\ - param opt eyepos EyePosition\n\ param opt entmatrix entmatrix\n\ \ - {\n\ - map $shadowmap\n\ - blendfunc add\n\ - tcgen base\n\ - }\n\ {\n\ map $diffuse\n\ - tcgen normal\n\ + blendfunc add\n\ }\n\ {\n\ map $normalmap\n\ - tcgen svector\n\ }\n\ {\n\ map $specular\n\ - tcgen tvector\n\ + }\n\ + {\n\ + map $shadowmap\n\ }\n\ }"; @@ -379,6 +354,7 @@ struct { mesh_t **meshes; unsigned int meshcount; + float modelmatrix[16]; float modelviewmatrix[16]; int pendingvertexvbo; @@ -388,7 +364,7 @@ struct { float identitylighting; //set to how bright lightmaps should be (reduced for overbright or realtime_world_lightmaps) - texid_t temptexture; + texid_t temptexture; //$current texid_t fogtexture; float fogfar; }; @@ -424,6 +400,49 @@ struct { int shadowsurfcount; } bench; +static void BE_PolyOffset(qboolean pushdepth) +{ + if (pushdepth) + { + /*some quake doors etc are flush with the walls that they're meant to be hidden behind, or plats the same height as the floor, etc + we move them back very slightly using polygonoffset to avoid really ugly z-fighting*/ + extern cvar_t r_polygonoffset_submodel_offset, r_polygonoffset_submodel_factor; + polyoffset_t po; + po.factor = shaderstate.curshader->polyoffset.factor + r_polygonoffset_submodel_factor.value; + po.unit = shaderstate.curshader->polyoffset.unit + r_polygonoffset_submodel_offset.value; + +#ifndef FORCESTATE + if (((int*)&shaderstate.curpolyoffset)[0] != ((int*)&po)[0] || ((int*)&shaderstate.curpolyoffset)[1] != ((int*)&po)[1]) +#endif + { + shaderstate.curpolyoffset = po; + if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit) + { + qglEnable(GL_POLYGON_OFFSET_FILL); + qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit); + } + else + qglDisable(GL_POLYGON_OFFSET_FILL); + } + } + else + { +#ifndef FORCESTATE + if (*(int*)&shaderstate.curpolyoffset != *(int*)&shaderstate.curshader->polyoffset || *(int*)&shaderstate.curpolyoffset != *(int*)&shaderstate.curshader->polyoffset) +#endif + { + shaderstate.curpolyoffset = shaderstate.curshader->polyoffset; + if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit) + { + qglEnable(GL_POLYGON_OFFSET_FILL); + qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit); + } + else + qglDisable(GL_POLYGON_OFFSET_FILL); + } + } +} + void GL_TexEnv(GLenum mode) { #ifndef FORCESTATE @@ -877,7 +896,7 @@ static void T_Gen_CurrentRender(int tmu) } // copy the scene to texture if (!TEXVALID(shaderstate.temptexture)) - shaderstate.temptexture = GL_AllocNewTexture(vwidth, vheight); + TEXASSIGN(shaderstate.temptexture, GL_AllocNewTexture("***$currentrender***", vwidth, vheight)); GL_MTBind(tmu, GL_TEXTURE_2D, shaderstate.temptexture); qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, vwidth, vheight, 0); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -886,14 +905,11 @@ static void T_Gen_CurrentRender(int tmu) static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolean useclientarray) { + extern texid_t scenepp_postproc_cube; texid_t t; switch(pass->texgen) { default: - case T_GEN_SKYBOX: - t = pass->anim_frames[0]; - GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t, useclientarray); - return; case T_GEN_SINGLEMAP: t = pass->anim_frames[0]; break; @@ -928,6 +944,15 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolea t = shaderstate.curshadowmap; break; + case T_GEN_SKYBOX: + t = pass->anim_frames[0]; + GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t, useclientarray); + return; + case T_GEN_SOURCECUBE: + t = scenepp_postproc_cube; + GL_LazyBind(tmu, GL_TEXTURE_CUBE_MAP_ARB, t, useclientarray); + return; + case T_GEN_VIDEOMAP: #ifdef NOMEDIA t = shaderstate.curtexnums?shaderstate.curtexnums->base:r_nulltex; @@ -1070,7 +1095,7 @@ void GenerateFogTexture(texid_t *tex, float density, float zscale) } if (!TEXVALID(*tex)) - *tex = R_AllocNewTexture(FOGS, FOGT); + *tex = R_AllocNewTexture("***fog***", FOGS, FOGT); R_Upload(*tex, "fog", TF_RGBA32, fogdata, NULL, FOGS, FOGT, IF_CLAMP|IF_NOMIPMAP); } @@ -1133,6 +1158,8 @@ void GLBE_Init(void) r_worldentity.axis[0][0] = 1; r_worldentity.axis[1][1] = 1; r_worldentity.axis[2][2] = 1; + + R_InitFlashblends(); } //end tables @@ -1428,15 +1455,35 @@ static void colourgen(const shaderpass_t *pass, int cnt, vec4_t *src, vec4_t *ds dst[cnt][2] = 1-shaderstate.curentity->shaderRGBAf[2]; } break; - case RGB_GEN_VERTEX: - case RGB_GEN_EXACT_VERTEX: + case RGB_GEN_VERTEX_LIGHTING: + if (shaderstate.identitylighting != 1) + { + if (!src) + { + while((cnt)--) + { + dst[cnt][0] = shaderstate.identitylighting; + dst[cnt][1] = shaderstate.identitylighting; + dst[cnt][2] = shaderstate.identitylighting; + } + break; + } + while((cnt)--) + { + dst[cnt][0] = src[cnt][0]*shaderstate.identitylighting; + dst[cnt][1] = src[cnt][1]*shaderstate.identitylighting; + dst[cnt][2] = src[cnt][2]*shaderstate.identitylighting; + } + break; + } + case RGB_GEN_VERTEX_EXACT: if (!src) { while((cnt)--) { - dst[cnt][0] = shaderstate.identitylighting; - dst[cnt][1] = shaderstate.identitylighting; - dst[cnt][2] = shaderstate.identitylighting; + dst[cnt][0] = 1; + dst[cnt][1] = 1; + dst[cnt][2] = 1; } break; } @@ -1495,7 +1542,7 @@ static void colourgen(const shaderpass_t *pass, int cnt, vec4_t *src, vec4_t *ds } else { - R_LightArrays(shaderstate.curentity, mesh->xyz_array, dst, cnt, mesh->normals_array); + R_LightArrays(shaderstate.curentity, mesh->xyz_array, dst, cnt, mesh->normals_array, shaderstate.identitylighting); } break; case RGB_GEN_WAVE: @@ -1983,7 +2030,7 @@ static void GenerateColourMods(const shaderpass_t *pass) qglShadeModel(GL_SMOOTH); //if its vetex lighting, just use the vbo - if ((pass->rgbgen == RGB_GEN_VERTEX || pass->rgbgen == RGB_GEN_EXACT_VERTEX) && pass->alphagen == ALPHA_GEN_VERTEX) + if (((pass->rgbgen == RGB_GEN_VERTEX_LIGHTING && shaderstate.identitylighting == 1) || pass->rgbgen == RGB_GEN_VERTEX_EXACT) && pass->alphagen == ALPHA_GEN_VERTEX) { GL_SelectVBO(shaderstate.sourcevbo->vbocolours); qglColorPointer(4, GL_FLOAT, 0, shaderstate.sourcevbo->colours4f); @@ -2061,8 +2108,8 @@ static void BE_SendPassBlendDepthMask(unsigned int sbits) unsigned int delta; /*2d mode doesn't depth test or depth write*/ -#ifdef _MSC_VER -#pragma message("fixme: q3 doesn't seem to have this, why do we need it?") +#ifdef warningmsg +#pragma warningmsg("fixme: q3 doesn't seem to have this, why do we need it?") #endif if (shaderstate.force2d) { @@ -2441,20 +2488,7 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned } break; case SP_M_MODEL: - { - float m16[16]; - Matrix4x4_CM_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); -/* VectorCopy(shaderstate.curentity->axis[0], m16+0); - m16[3] = 0; - VectorCopy(shaderstate.curentity->axis[1], m16+1); - m16[7] = 0; - VectorCopy(shaderstate.curentity->axis[2], m16+2); - m16[11] = 0; - VectorCopy(shaderstate.curentity->origin, m16+3); - m16[15] = 1; -*/ - qglUniformMatrix4fvARB(p->handle[perm], 1, false, m16); - } + qglUniformMatrix4fvARB(p->handle[perm], 1, false, shaderstate.modelmatrix); break; case SP_M_ENTBONES: { @@ -2532,35 +2566,21 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned break; case SP_E_EYEPOS: { - float m16[16]; -#ifdef _MSC_VER -#pragma message("is this correct?") -#endif -// vec3_t t1; + /*eye position in model space*/ vec3_t t2; - Matrix4x4_CM_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); - Matrix4x4_CM_Transform3(m16, r_origin, t2); -// VectorSubtract(r_origin, shaderstate.curentity->origin, t1); -// Matrix3_Multiply_Vec3(shaderstate.curentity->axis, t1, t2); + Matrix4x4_CM_Transform3(shaderstate.modelmatrix, r_origin, t2); qglUniform3fvARB(p->handle[perm], 1, t2); } break; case SP_LIGHTPOSITION: { -#ifdef _MSC_VER -#pragma message("is this correct?") -#endif + /*light position in model space*/ float inv[16]; - float m16[16]; -// vec3_t t1; vec3_t t2; qboolean Matrix4_Invert(const float *m, float *out); - Matrix4x4_CM_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); - Matrix4_Invert(m16, inv); + Matrix4_Invert(shaderstate.modelmatrix, inv); Matrix4x4_CM_Transform3(inv, shaderstate.lightorg, t2); -// VectorSubtract(shaderstate.lightorg, shaderstate.curentity->origin, t1); -// Matrix3_Multiply_Vec3(shaderstate.curentity->axis, t1, t2); qglUniform3fvARB(p->handle[perm], 1, t2); } break; @@ -2721,7 +2741,7 @@ qboolean GLBE_LightCullModel(vec3_t org, model_t *model) return false; } -//Note: Be cautious about using BEM_LIGHT here. +//Note: Be cautious about using BEM_LIGHT here, as it won't select the light. void GLBE_SelectMode(backendmode_t mode) { extern int gldepthfunc; @@ -2730,10 +2750,36 @@ void GLBE_SelectMode(backendmode_t mode) { shaderstate.mode = mode; shaderstate.flags = 0; -#ifdef RTLIGHTS - if (mode == BEM_STENCIL) + switch (mode) { + case BEM_DEPTHONLY: GL_DeSelectProgram(); + /*BEM_DEPTHONLY does support mesh writing, but its not the only way its used... FIXME!*/ + qglDisableClientState(GL_COLOR_ARRAY); + while(shaderstate.lastpasstmus>0) + { + GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); + } + qglShadeModel(GL_FLAT); + + //we don't write or blend anything (maybe alpha test... but mneh) + BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHWRITE | SBITS_MASK_BITS); + + BE_SetPassBlendMode(0, PBM_REPLACE); + GL_CullFace(SHADER_CULL_FRONT); + break; + +#ifdef RTLIGHTS + case BEM_STENCIL: + GL_DeSelectProgram(); + + if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit) + { + shaderstate.curpolyoffset.factor = 0; + shaderstate.curpolyoffset.unit = 0; + qglDisable(GL_POLYGON_OFFSET_FILL); + } + /*BEM_STENCIL doesn't support mesh writing*/ qglDisableClientState(GL_COLOR_ARRAY); //disable all tmus @@ -2751,52 +2797,33 @@ void GLBE_SelectMode(backendmode_t mode) //don't change cull stuff, and //don't actually change stencil stuff - caller needs to be //aware of how many times stuff is drawn, so they can do that themselves. - } -#endif - if (mode == BEM_DEPTHONLY) - { - GL_DeSelectProgram(); - /*BEM_DEPTHONLY does support mesh writing, but its not the only way its used... FIXME!*/ - qglDisableClientState(GL_COLOR_ARRAY); - while(shaderstate.lastpasstmus>0) - { - GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); - } - qglShadeModel(GL_FLAT); + break; - //we don't write or blend anything (maybe alpha test... but mneh) - BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHWRITE | SBITS_MASK_BITS); - - BE_SetPassBlendMode(0, PBM_REPLACE); - GL_CullFace(SHADER_CULL_FRONT); - } -#ifdef RTLIGHTS - if (mode == BEM_SMAPLIGHT) - { + case BEM_SMAPLIGHT: if (!shaderstate.initedpcfpasses) { shaderstate.initedpcfpasses = true; shaderstate.pcfpassshader = R_RegisterCustom("lightpass_pcf", Shader_LightPass_PCF, NULL); } - } - if (mode == BEM_SMAPLIGHTSPOT) - { + break; + + case BEM_SMAPLIGHTSPOT: if (!shaderstate.initedspotpasses) { shaderstate.initedspotpasses = true; shaderstate.spotpassshader = R_RegisterCustom("lightpass_spot", Shader_LightPass_Spot, NULL); } - } - if (mode == BEM_LIGHT) - { + break; + + case BEM_LIGHT: if (!shaderstate.initedlightpasses) { shaderstate.initedlightpasses = true; shaderstate.lightpassshader = R_RegisterCustom("lightpass", Shader_LightPass_Std, NULL); } - } - if (mode == BEM_FOG) - { + break; +#endif + case BEM_FOG: while(shaderstate.lastpasstmus>0) { GL_LazyBind(--shaderstate.lastpasstmus, 0, r_nulltex, false); @@ -2809,8 +2836,8 @@ void GLBE_SelectMode(backendmode_t mode) qglShadeModel(GL_FLAT); BE_SetPassBlendMode(0, PBM_MODULATE); BE_SendPassBlendDepthMask(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | SBITS_MISC_DEPTHEQUALONLY); + break; } -#endif } } @@ -2820,7 +2847,7 @@ void GLBE_SelectEntity(entity_t *ent) qglDepthRange (gldepthmin, gldepthmax); shaderstate.curentity = ent; currententity = ent; - R_RotateForEntity(shaderstate.modelviewmatrix, shaderstate.curentity, shaderstate.curentity->model); + R_RotateForEntity(shaderstate.modelmatrix, shaderstate.modelviewmatrix, shaderstate.curentity, shaderstate.curentity->model); if (qglLoadMatrixf) qglLoadMatrixf(shaderstate.modelviewmatrix); if (shaderstate.curentity->flags & Q2RF_DEPTHHACK && qglDepthRange) @@ -2840,7 +2867,7 @@ void BE_SelectFog(vec3_t colour, float alpha, float density) qglColor4f(colour[0], colour[1], colour[2], alpha); } -void BE_SelectDLight(dlight_t *dl, vec3_t colour) +void GLBE_SelectDLight(dlight_t *dl, vec3_t colour) { shaderstate.lightradius = dl->radius; VectorCopy(dl->origin, shaderstate.lightorg); @@ -2893,49 +2920,6 @@ void BE_PushOffsetShadow(qboolean pushdepth) } } -void BE_PolyOffset(qboolean pushdepth) -{ - if (pushdepth) - { - /*some quake doors etc are flush with the walls that they're meant to be hidden behind, or plats the same height as the floor, etc - we move them back very slightly using polygonoffset to avoid really ugly z-fighting*/ - extern cvar_t r_polygonoffset_submodel_offset, r_polygonoffset_submodel_factor; - polyoffset_t po; - po.factor = shaderstate.curshader->polyoffset.factor + r_polygonoffset_submodel_factor.value; - po.unit = shaderstate.curshader->polyoffset.unit + r_polygonoffset_submodel_offset.value; - -#ifndef FORCESTATE - if (((int*)&shaderstate.curpolyoffset)[0] != ((int*)&po)[0] || ((int*)&shaderstate.curpolyoffset)[1] != ((int*)&po)[1]) -#endif - { - shaderstate.curpolyoffset = po; - if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit) - { - qglEnable(GL_POLYGON_OFFSET_FILL); - qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit); - } - else - qglDisable(GL_POLYGON_OFFSET_FILL); - } - } - else - { -#ifndef FORCESTATE - if (*(int*)&shaderstate.curpolyoffset != *(int*)&shaderstate.curshader->polyoffset || *(int*)&shaderstate.curpolyoffset != *(int*)&shaderstate.curshader->polyoffset) -#endif - { - shaderstate.curpolyoffset = shaderstate.curshader->polyoffset; - if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit) - { - qglEnable(GL_POLYGON_OFFSET_FILL); - qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit); - } - else - qglDisable(GL_POLYGON_OFFSET_FILL); - } - } -} - static void DrawMeshes(void) { const shaderpass_t *p; @@ -3007,8 +2991,8 @@ static void DrawMeshes(void) #endif case BEM_DEPTHONLY: GL_DeSelectProgram(); -#ifdef _MSC_VER -#pragma message("fixme: support alpha test") +#ifdef warningmsg +#pragma warningmsg("fixme: support alpha test") #endif GL_ApplyVertexPointer(); BE_SubmitMeshChain(); @@ -3273,7 +3257,7 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist) continue; if (batch->shader->flags & SHADER_SKY) { - if (shaderstate.mode == BEM_STANDARD) + if (shaderstate.mode == BEM_STANDARD || shaderstate.mode == BEM_DEPTHDARK) { if (!batch->shader->prog) { @@ -3381,7 +3365,7 @@ void BE_BaseEntTextures(void) { batch_t *batches[SHADER_SORT_COUNT]; BE_GenModelBatches(batches); - GLBE_SubmitMeshes(false, batches, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST); + GLBE_SubmitMeshes(false, batches, SHADER_SORT_PORTAL, SHADER_SORT_DECAL); BE_SelectEntity(&r_worldentity); } #endif @@ -3423,7 +3407,7 @@ void GLBE_DrawLightPrePass(qbyte *vis, batch_t **batches) #define GL_RGBA32F_ARB 0x8814 if (!TEXVALID(shaderstate.tex_normals)) { - shaderstate.tex_normals = GL_AllocNewTexture(vid.pixelwidth, vid.pixelheight); + shaderstate.tex_normals = GL_AllocNewTexture("***prepass normals***", vid.pixelwidth, vid.pixelheight); r_lightprepass.modified = true; } if (r_lightprepass.modified) @@ -3439,7 +3423,7 @@ void GLBE_DrawLightPrePass(qbyte *vis, batch_t **batches) { int drb; - shaderstate.tex_diffuse = GL_AllocNewTexture(vid.pixelwidth, vid.pixelheight); + shaderstate.tex_diffuse = GL_AllocNewTexture("***prepass diffuse***", vid.pixelwidth, vid.pixelheight); GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_diffuse); qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth, vid.pixelheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -3469,6 +3453,7 @@ void GLBE_DrawLightPrePass(qbyte *vis, batch_t **batches) /*set the FB up to draw surface info*/ qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, shaderstate.tex_normals.num, 0); + GL_ForceDepthWritable(); qglClear(GL_DEPTH_BUFFER_BIT); if (GL_FRAMEBUFFER_COMPLETE_EXT != qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)) @@ -3563,7 +3548,7 @@ void GLBE_DrawWorld (qbyte *vis) else #endif shaderstate.identitylighting = 1; - // shaderstate.identitylighting /= 1<next = gltextures; + gltextures = glt; + + glt->texnum.ref = &glt->com; + Q_strncpyz (glt->identifier, ident, sizeof(glt->identifier)); + glt->flags = IF_NOMIPMAP; + glt->width = w; + glt->height = h; + glt->bpp = 0; + glt->com.regsequence = r_regsequence; + + qglGenTextures(1, &glt->texnum.num); + + Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); + return glt; +} + +texid_t GL_AllocNewTexture(char *name, int w, int h) +{ + gltexture_t *glt = GL_AllocNewGLTexture(name, w, h); + return glt->texnum; +} + +void GL_DestroyTexture(texid_t tex) +{ + if (!tex.ref) + return; + + qglDeleteTextures(1, &tex.num); +} + //============================================================================= /* Support Routines */ @@ -259,7 +293,10 @@ void GL_Texturemode_Callback (struct cvar_s *var, char *oldvalue) { GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); + if (glt->flags & IF_NEAREST) + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); } } } @@ -294,17 +331,49 @@ void GL_Texturemode2d_Callback (struct cvar_s *var, char *oldvalue) { GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); + if (glt->flags & IF_NEAREST) + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); } } } + +void GLDraw_ImageList_f(void) +{ + int count = 0; + gltexture_t *glt; + for (glt=gltextures ; glt ; glt=glt->next) + { + count++; + Con_Printf("%s (%i*%i, seq=%i)\n", glt->identifier, glt->width, glt->height, glt->com.regsequence); + } + Con_Printf("%i images\n", count); +} + +void GLDraw_FlushOldTextures(void) +{ + gltexture_t **link = &gltextures, *t; + while (*link) + { + t = *link; + if (t->com.regsequence != r_regsequence) + { + qglDeleteTextures(1, &t->texnum.num); + (*link)->next = t->next; + BZ_Free(t); + } + else + link = &(*link)->next; + } +} + /* =============== Draw_Init =============== */ - -void GLDraw_ReInit (void) +void GLDraw_Init (void) { char ver[40]; @@ -319,9 +388,6 @@ void GLDraw_ReInit (void) memset(gltexturetablebuckets, 0, sizeof(gltexturetablebuckets)); Hash_InitTable(&gltexturetable, sizeof(gltexturetablebuckets)/sizeof(gltexturetablebuckets[0]), gltexturetablebuckets); - lightmap_textures=NULL; - filmtexture=r_nulltex; - GL_FlushBackEnd(); // GL_FlushSkinCache(); TRACE(("dbg: GLDraw_ReInit: GL_GAliasFlushSkinCache\n")); @@ -393,18 +459,13 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); TRACE(("dbg: GLDraw_ReInit: PPL_LoadSpecularFragmentProgram\n")); GL_InitSceneProcessingShaders(); + + Cmd_AddRemCommand ("r_imagelist", GLDraw_ImageList_f); } -void GLDraw_Init (void) -{ -// memset(scrap_allocated, 0, sizeof(scrap_allocated)); -// memset(scrap_texels, 255, sizeof(scrap_texels)); - - GLDraw_ReInit(); -} void GLDraw_DeInit (void) { - Cmd_RemoveCommand ("gl_texture_anisotropic_filtering"); + Cmd_RemoveCommand ("r_imagelist"); if (font_conchar) Font_Free(font_conchar); @@ -434,6 +495,7 @@ void GLDraw_DeInit (void) gltexture_t *glt; glt = gltextures; gltextures = gltextures->next; + BZ_Free(glt); } @@ -921,12 +983,18 @@ qboolean GL_UploadCompressed (qbyte *file, int *out_width, int *out_height, unsi if (!((*out_flags) & IF_NOMIPMAP)) { qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); + if (*out_flags & IF_NEAREST) + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); } else { qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); + if (*out_flags & IF_NEAREST) + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); } return true; } @@ -1090,16 +1158,22 @@ void GL_Upload32_Int (char *name, unsigned *data, int width, int height, unsigne TRACE(("dbg: GL_Upload32: GL_SGIS_generate_mipmap\n")); qglTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); } - + if (!(flags&IF_NOMIPMAP)) { qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); + if (flags & IF_NEAREST) + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); } else { qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); + if (flags & IF_NEAREST) + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); } if (flags&IF_CLAMP) @@ -1430,12 +1504,18 @@ done: ; if (!(flags&IF_NOMIPMAP)) { qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); + if (flags & IF_NEAREST) + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); } else { qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); + if (flags & IF_NEAREST) + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); } } @@ -1623,12 +1703,18 @@ void GL_UploadBump(qbyte *data, int width, int height, qboolean mipmap, float bu if (mipmap) { qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); + if (0 & IF_NEAREST) + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); } else { qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); + if (0 & IF_NEAREST) + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); } // if (gl_texturefilteranisotropic) @@ -1713,12 +1799,18 @@ done: ; if (mipmap) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); + if (flags & IF_NEAREST) + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); } else { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max_2d); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); + if (flags & IF_NEAREST) + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + else + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max_2d); } } #endif @@ -1993,18 +2085,10 @@ TRACE(("dbg: GL_LoadTexture: duplicate %s\n", identifier)); TRACE(("dbg: GL_LoadTexture: new %s\n", identifier)); - glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); - glt->next = gltextures; - gltextures = glt; - - strcpy (glt->identifier, identifier); - glt->texnum = GL_AllocNewTexture(width, height); - glt->width = width; - glt->height = height; + glt = GL_AllocNewGLTexture(identifier, width, height); glt->bpp = 8; glt->flags = flags; - Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); checkglerror(); GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); @@ -2033,19 +2117,10 @@ texid_t GL_LoadTextureFB (char *identifier, int width, int height, qbyte *data, if (i == width*height) return r_nulltex; //none found, don't bother uploading. - glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); - glt->next = gltextures; - gltextures = glt; - - strcpy (glt->identifier, identifier); - glt->texnum = GL_AllocNewTexture(width, height); - glt->width = width; - glt->height = height; + glt = GL_AllocNewGLTexture(identifier, width, height); glt->bpp = 8; glt->flags = flags; - Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload8FB (data, width, height, flags); @@ -2065,20 +2140,10 @@ texid_t GL_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *da return glt->texnum; } - glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); - glt->next = gltextures; - gltextures = glt; - - - strcpy (glt->identifier, identifier); - glt->texnum = GL_AllocNewTexture(width, height); - glt->width = width; - glt->height = height; + glt = GL_AllocNewGLTexture(identifier, width, height); glt->bpp = 24; glt->flags = flags; - Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload8Pal24 (data, palette24, width, height, flags); @@ -2097,20 +2162,10 @@ texid_t GL_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *da return glt->texnum; } - glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); - glt->next = gltextures; - gltextures = glt; - - - strcpy (glt->identifier, identifier); - glt->texnum = GL_AllocNewTexture(width, height); - glt->width = width; - glt->height = height; + glt = GL_AllocNewGLTexture(identifier, width, height); glt->bpp = 32; glt->flags = flags; - Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload8Pal32 (data, palette32, width, height, flags); @@ -2132,19 +2187,10 @@ texid_t GL_LoadTexture32 (char *identifier, int width, int height, void *data, u return glt->texnum; } - glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); - glt->next = gltextures; - gltextures = glt; - - strcpy (glt->identifier, identifier); - glt->texnum = GL_AllocNewTexture(width, height); - glt->width = width; - glt->height = height; + glt = GL_AllocNewGLTexture(identifier, width, height); glt->bpp = 32; glt->flags = flags; - Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload32 (identifier, data, width, height, flags); @@ -2166,19 +2212,10 @@ texid_t GL_LoadTexture32_BGRA (char *identifier, int width, int height, unsigned return glt->texnum; } - glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); - glt->next = gltextures; - gltextures = glt; - - strcpy (glt->identifier, identifier); - glt->texnum = GL_AllocNewTexture(width, height); - glt->width = width; - glt->height = height; + glt = GL_AllocNewGLTexture(identifier, width, height); glt->bpp = 32; glt->flags = flags; - Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload32_BGRA (identifier, data, width, height, flags); @@ -2212,17 +2249,10 @@ texid_t GL_LoadCompressed(char *name) if (!file) return r_nulltex; - glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); - glt->next = gltextures; - gltextures = glt; - - strcpy (glt->identifier, name); - glt->texnum = GL_AllocNewTexture(0, 0); + glt = GL_AllocNewGLTexture(name, 0, 0); glt->bpp = 32; glt->flags = 0; - Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); if (!GL_UploadCompressed(file, &glt->width, &glt->height, (unsigned int *)&glt->flags)) @@ -2247,19 +2277,10 @@ texid_t GL_LoadTexture8Grey (char *identifier, int width, int height, unsigned c flags |= IF_NOALPHA; - glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); - glt->next = gltextures; - gltextures = glt; - - strcpy (glt->identifier, identifier); - glt->texnum = GL_AllocNewTexture(width, height); - glt->width = width; - glt->height = height; + glt = GL_AllocNewGLTexture(identifier, width, height); glt->bpp = 8; glt->flags = flags; - Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_Upload8Grey (data, width, height, flags); @@ -2286,19 +2307,10 @@ texid_t GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned c TRACE(("dbg: GL_LoadTexture8Bump: new %s\n", identifier)); - glt = BZ_Malloc(sizeof(*glt)+sizeof(bucket_t)); - glt->next = gltextures; - gltextures = glt; - - strcpy (glt->identifier, identifier); - glt->texnum = GL_AllocNewTexture(width, height); - glt->width = width; - glt->height = height; + glt = GL_AllocNewGLTexture(identifier, width, height); glt->bpp = 8; glt->flags = flags; - Hash_Add(&gltexturetable, glt->identifier, glt, (bucket_t*)(glt+1)); - GL_MTBind(0, GL_TEXTURE_2D, glt->texnum); GL_UploadBump (data, width, height, flags, bumpscale); diff --git a/engine/gl/gl_draw.h b/engine/gl/gl_draw.h index 6dc922b6d..33157dc5e 100644 --- a/engine/gl/gl_draw.h +++ b/engine/gl/gl_draw.h @@ -22,7 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // to touch the vid buffer void GLDraw_Init (void); -void GLDraw_ReInit (void); void GLDraw_DeInit (void); void Surf_DeInit (void); diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 0150d5de1..bf5513967 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -228,7 +228,7 @@ static struct font_s *curfont; void Font_Init(void) { int i; - fontplanes.defaultfont = r_nulltex; + TEXASSIGN(fontplanes.defaultfont, r_nulltex); font_foremesh.indexes = font_indicies; font_foremesh.xyz_array = font_coord; @@ -252,7 +252,7 @@ void Font_Init(void) for (i = 0; i < FONTPLANES; i++) { - fontplanes.texnum[i] = R_AllocNewTexture(PLANEWIDTH, PLANEHEIGHT); + TEXASSIGN(fontplanes.texnum[i], R_AllocNewTexture("***fontplane***", PLANEWIDTH, PLANEHEIGHT)); } fontplanes.shader = R_RegisterShader("ftefont", @@ -293,7 +293,7 @@ static void Font_Flush(void) return; if (fontplanes.planechanged) { - R_Upload(fontplanes.texnum[fontplanes.activeplane], NULL, TF_RGBA32, (void*)fontplanes.plane, NULL, PLANEWIDTH, PLANEHEIGHT, IF_NOPICMIP|IF_NOMIPMAP|IF_NOGAMMA); + R_Upload(fontplanes.texnum[fontplanes.activeplane], NULL, TF_RGBA32, (void*)fontplanes.plane, NULL, PLANEWIDTH, PLANEHEIGHT, IF_NEAREST|IF_NOPICMIP|IF_NOMIPMAP|IF_NOGAMMA); fontplanes.planechanged = false; } @@ -306,7 +306,7 @@ static void Font_Flush(void) BE_DrawMesh_Single(fontplanes.backshader, &font_backmesh, NULL, &fontplanes.backshader->defaulttextures, 0); } - fontplanes.shader->defaulttextures.base = font_texture; + TEXASSIGN(fontplanes.shader->defaulttextures.base, font_texture); BE_DrawMesh_Single(fontplanes.shader, &font_foremesh, NULL, &fontplanes.shader->defaulttextures, 0); font_foremesh.numindexes = 0; font_foremesh.numvertexes = 0; @@ -319,7 +319,7 @@ static int Font_BeginChar(texid_t tex) if (font_foremesh.numindexes == FONT_CHAR_BUFFER*6 || memcmp(&font_texture,&tex, sizeof(texid_t))) { Font_Flush(); - font_texture = tex; + TEXASSIGNF(font_texture, tex); } fvert = font_foremesh.numvertexes; @@ -336,7 +336,7 @@ void Font_Shutdown(void) int i; for (i = 0; i < FONTPLANES; i++) - fontplanes.texnum[i] = r_nulltex; + TEXASSIGN(fontplanes.texnum[i], r_nulltex); fontplanes.activeplane = 0; fontplanes.oldestchar = NULL; fontplanes.newestchar = NULL; diff --git a/engine/gl/gl_hlmdl.c b/engine/gl/gl_hlmdl.c index 66c63abf7..2b8c2f282 100644 --- a/engine/gl/gl_hlmdl.c +++ b/engine/gl/gl_hlmdl.c @@ -126,9 +126,11 @@ qboolean Mod_LoadHLModel (model_t *mod, void *buffer) #if defined(HLSERVER) && (defined(__powerpc__) || defined(__ppc__)) //this is to let bigfoot know when he comes to port it all... And I'm lazy. -#warning "-----------------------------------------" -#warning "FIXME: No byteswapping on halflife models" -#warning "-----------------------------------------" +#ifdef warningmsg +#pragma warningmsg("-----------------------------------------") +#pragma warningmsg("FIXME: No byteswapping on halflife models") +#pragma warningmsg("-----------------------------------------") +#endif #endif if (header->version != 10) @@ -566,7 +568,7 @@ void R_DrawHLModel(entity_t *curent) int b, m, v; short *skins; int bgroup, cbone, lastbone; - float mat[16]; + float mmat[16], mvmat[16]; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ //general model @@ -610,8 +612,8 @@ void R_DrawHLModel(entity_t *curent) qglColor4f(difuse[0]/255+ambient[0]/255, difuse[1]/255+ambient[1]/255, difuse[2]/255+ambient[2]/255, curent->shaderRGBAf[3]); } - R_RotateForEntity (mat, curent, curent->model); - qglLoadMatrixf(mat); + R_RotateForEntity (mmat, mvmat, curent, curent->model); + qglLoadMatrixf(mvmat); cbone = 0; for (bgroup = 0; bgroup < FS_COUNT; bgroup++) diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 9db811799..11bd55072 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -31,9 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern cvar_t r_shadow_bumpscale_basetexture; extern cvar_t r_replacemodels; -extern cvar_t r_deluxemapping; -extern int gl_bumpmappingpossible; qboolean isnotmap = true; //used to not warp ammo models. model_t *loadmodel; @@ -140,7 +138,6 @@ void RMod_BlockTextureColour_f (void) int i, m; unsigned int colour[8*8]; unsigned int rgba; - texnums_t tn; ((char *)&rgba)[0] = atoi(Cmd_Argv(2)); ((char *)&rgba)[1] = atoi(Cmd_Argv(3)); @@ -152,8 +149,6 @@ void RMod_BlockTextureColour_f (void) s = R_RegisterCustom(Cmd_Argv(2), NULL, NULL); if (!s) { - memset(&tn, 0, sizeof(tn)); - tn.base = R_LoadTexture32(texname, 8, 8, colour, IF_NOALPHA|IF_NOGAMMA); s = R_RegisterCustom (texname, Shader_DefaultBSPQ1, NULL); } @@ -1183,10 +1178,9 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n")); } tn.bump = r_nulltex; - if (gl_bumpmappingpossible && cls.allow_bump) + if (r_loadbumpmapping) { - extern cvar_t gl_bump; - if (gl_bump.ival<2) //set to 2 to have faster loading. + if (r_loadbumpmapping) { snprintf(altname, sizeof(altname)-1, "%s_norm", mt->name); tn.bump = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY); @@ -1373,7 +1367,7 @@ void RMod_NowLoadExternal(void) tn.base = R_LoadReplacementTexture("light1_4", NULL, IF_NOALPHA); //a fallback. :/ } } - if (!TEXVALID(tn.bump) && *tx->name != '{' && gl_bumpmappingpossible && cls.allow_bump) + if (!TEXVALID(tn.bump) && *tx->name != '{' && r_loadbumpmapping) { tn.bump = R_LoadBumpmapTexture(va("%s_bump", tx->name), loadname); if (!TEXVALID(tn.bump)) @@ -1442,8 +1436,17 @@ void RMod_LoadLighting (lump_t *l) { qbyte *luxdata = NULL; int mapcomeswith24bitcolouredlighting = false; + extern cvar_t gl_overbright; loadmodel->engineflags &= ~MDLF_RGBLIGHTING; + //q3 maps have built in 4-fold overbright. + //if we're not rendering with that, we need to brighten the lightmaps in order to keep the darker parts the same brightness. we loose the 2 upper bits. those bright areas become uniform and indistinct. + if (loadmodel->fromgame == fg_quake3) + { + gl_overbright.flags |= CVAR_LATCH; + BuildLightMapGammaTable(1, (1<<(2-gl_overbright.ival))); + } + else //lit file light intensity is made to match the world's light intensity. // if (cls.allow_lightmapgamma) // BuildLightMapGammaTable(0.6, 2); @@ -1460,7 +1463,7 @@ void RMod_LoadLighting (lump_t *l) if (loadmodel->fromgame == fg_halflife || loadmodel->fromgame == fg_quake2 || loadmodel->fromgame == fg_quake3) mapcomeswith24bitcolouredlighting = true; - if (!mapcomeswith24bitcolouredlighting && r_loadlits.ival && gl_bumpmappingpossible && r_deluxemapping.ival) //fixme: adjust the light intensities. + if (!mapcomeswith24bitcolouredlighting && r_loadlits.ival && r_deluxemapping.ival) //fixme: adjust the light intensities. { //the map util has a '-scalecos X' parameter. use 0 if you're going to use only just lux. without lux scalecos 0 is hideous. char luxname[MAX_QPATH]; if (!luxdata) @@ -1601,7 +1604,7 @@ void RMod_LoadLighting (lump_t *l) loadmodel->engineflags |= MDLF_RGBLIGHTING; #ifdef RUNTIMELIGHTING - else if (r_loadlits.value == 2 && !lightmodel && (!(loadmodel->engineflags & MDLF_RGBLIGHTING) || (!luxdata && gl_bumpmappingpossible))) + else if (r_loadlits.value == 2 && !lightmodel && (!(loadmodel->engineflags & MDLF_RGBLIGHTING) || (!luxdata && r_deluxemapping.ival))) { qbyte *litdata = NULL; int i; @@ -1623,7 +1626,7 @@ void RMod_LoadLighting (lump_t *l) normal++; } - if (gl_bumpmappingpossible) + if (r_deluxemapping.ival) { loadmodel->deluxdata = Hunk_AllocName ( l->filelen*3+8, loadname); strcpy(loadmodel->deluxdata, "QLIT"); @@ -1846,28 +1849,50 @@ qboolean RMod_LoadSubmodels (lump_t *l) Mod_LoadEdges ================= */ -qboolean RMod_LoadEdges (lump_t *l) +qboolean RMod_LoadEdges (lump_t *l, qboolean lm) { - dedge_t *in; medge_t *out; int i, count; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) + + if (lm) { - Con_Printf ("MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name); - return false; + dledge_t *in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + { + Con_Printf ("MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name); + return false; + } + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname); + + loadmodel->edges = out; + loadmodel->numedges = count; + + for ( i=0 ; iv[0] = LittleLong(in->v[0]); + out->v[1] = LittleLong(in->v[1]); + } } - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname); - - loadmodel->edges = out; - loadmodel->numedges = count; - - for ( i=0 ; iv[0] = (unsigned short)LittleShort(in->v[0]); - out->v[1] = (unsigned short)LittleShort(in->v[1]); + dsedge_t *in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + { + Con_Printf ("MOD_LoadBmodel: funny lump size in %s\n", loadmodel->name); + return false; + } + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname); + + loadmodel->edges = out; + loadmodel->numedges = count; + + for ( i=0 ; iv[0] = (unsigned short)LittleShort(in->v[0]); + out->v[1] = (unsigned short)LittleShort(in->v[1]); + } } return true; @@ -1923,7 +1948,10 @@ qboolean RMod_LoadTexinfo (lump_t *l) miptex = LittleLong (in->miptex); out->flags = LittleLong (in->flags); - out->texture = loadmodel->textures[miptex % loadmodel->numtextures]; + if (loadmodel->numtextures) + out->texture = loadmodel->textures[miptex % loadmodel->numtextures]; + else + out->texture = NULL; if (!out->texture) { out->texture = r_notexture_mip; // texture not found @@ -1996,56 +2024,85 @@ void CalcSurfaceExtents (msurface_t *s); Mod_LoadFaces ================= */ -qboolean RMod_LoadFaces (lump_t *l) +qboolean RMod_LoadFaces (lump_t *l, qboolean lm) { - dface_t *in; + dsface_t *ins; + dlface_t *inl; msurface_t *out; - int i, count, surfnum; - int planenum, side; - int tn; + int count, surfnum; + int i, planenum, side; + int tn, lofs; - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) + if (lm) { - Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); - return false; + ins = NULL; + inl = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*inl)) + { + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*inl); + } + else + { + ins = (void *)(mod_base + l->fileofs); + inl = NULL; + if (l->filelen % sizeof(*ins)) + { + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*ins); } - count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->surfaces = out; loadmodel->numsurfaces = count; - for ( surfnum=0 ; surfnumfirstedge = LittleLong(in->firstedge); - out->numedges = LittleShort(in->numedges); + if (lm) + { + planenum = LittleLong(inl->planenum); + side = LittleLong(inl->side); + out->firstedge = LittleLong(inl->firstedge); + out->numedges = LittleLong(inl->numedges); + tn = LittleLong (inl->texinfo); + for (i=0 ; istyles[i] = inl->styles[i]; + lofs = LittleLong(inl->lightofs); + inl++; + } + else + { + planenum = LittleShort(ins->planenum); + side = LittleShort(ins->side); + out->firstedge = LittleLong(ins->firstedge); + out->numedges = LittleShort(ins->numedges); + tn = LittleShort (ins->texinfo); + for (i=0 ; istyles[i] = ins->styles[i]; + lofs = LittleLong(ins->lightofs); + ins++; + } out->flags = 0; - planenum = LittleShort(in->planenum); - side = LittleShort(in->side); if (side) out->flags |= SURF_PLANEBACK; out->plane = loadmodel->planes + planenum; - tn = LittleShort (in->texinfo); if (tn < 0 || tn >= loadmodel->numtexinfo) Host_EndGame("Hey! That map has texinfos out of bounds!\n"); out->texinfo = loadmodel->texinfo + tn; CalcSurfaceExtents (out); - - // lighting info - - for (i=0 ; istyles[i] = in->styles[i]; - i = LittleLong(in->lightofs); - if (i == -1) + if (lofs == -1) out->samples = NULL; else if ((loadmodel->engineflags & MDLF_RGBLIGHTING) && loadmodel->fromgame != fg_halflife) - out->samples = loadmodel->lightdata + i*3; + out->samples = loadmodel->lightdata + lofs*3; else - out->samples = loadmodel->lightdata + i; + out->samples = loadmodel->lightdata + lofs; if (!out->texinfo->texture) continue; @@ -2113,45 +2170,87 @@ void RMod_SetParent (mnode_t *node, mnode_t *parent) Mod_LoadNodes ================= */ -qboolean RMod_LoadNodes (lump_t *l) +qboolean RMod_LoadNodes (lump_t *l, qboolean lm) { int i, j, count, p; - dnode_t *in; mnode_t *out; - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) + if (lm) { - Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); - return false; - } - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - loadmodel->nodes = out; - loadmodel->numnodes = count; - - for ( i=0 ; ifileofs); + if (l->filelen % sizeof(*in)) { - out->minmaxs[j] = LittleShort (in->mins[j]); - out->minmaxs[3+j] = LittleShort (in->maxs[j]); + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; } - - p = LittleLong(in->planenum); - out->plane = loadmodel->planes + p; + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); - out->firstsurface = LittleShort (in->firstface); - out->numsurfaces = LittleShort (in->numfaces); - - for (j=0 ; j<2 ; j++) + loadmodel->nodes = out; + loadmodel->numnodes = count; + + for ( i=0 ; ichildren[j]); - if (p >= 0) - out->children[j] = loadmodel->nodes + p; - else - out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); + for (j=0 ; j<3 ; j++) + { + out->minmaxs[j] = LittleShort (in->mins[j]); + out->minmaxs[3+j] = LittleShort (in->maxs[j]); + } + + p = LittleLong(in->planenum); + out->plane = loadmodel->planes + p; + + out->firstsurface = LittleLong (in->firstface); + out->numsurfaces = LittleLong (in->numfaces); + + for (j=0 ; j<2 ; j++) + { + p = LittleShort (in->children[j]); + if (p >= 0) + out->children[j] = loadmodel->nodes + p; + else + out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); + } + } + } + else + { + dsnode_t *in; + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + { + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->nodes = out; + loadmodel->numnodes = count; + + for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); + out->minmaxs[3+j] = LittleShort (in->maxs[j]); + } + + p = LittleLong(in->planenum); + out->plane = loadmodel->planes + p; + + out->firstsurface = LittleShort (in->firstface); + out->numsurfaces = LittleShort (in->numfaces); + + for (j=0 ; j<2 ; j++) + { + p = LittleShort (in->children[j]); + if (p >= 0) + out->children[j] = loadmodel->nodes + p; + else + out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); + } } } @@ -2164,66 +2263,125 @@ qboolean RMod_LoadNodes (lump_t *l) Mod_LoadLeafs ================= */ -qboolean RMod_LoadLeafs (lump_t *l) +qboolean RMod_LoadLeafs (lump_t *l, qboolean lm) { - dleaf_t *in; mleaf_t *out; int i, j, count, p; -// char s[80]; - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) + if (lm) { - Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); - return false; + dlleaf_t *in; + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + { + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); + + loadmodel->leafs = out; + loadmodel->numleafs = count; + + for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); + out->minmaxs[3+j] = LittleShort (in->maxs[j]); + } + + p = LittleLong(in->contents); + out->contents = p; + + out->firstmarksurface = loadmodel->marksurfaces + + LittleLong(in->firstmarksurface); + out->nummarksurfaces = LittleLong(in->nummarksurfaces); + + p = LittleLong(in->visofs); + if (p == -1) + out->compressed_vis = NULL; + else + out->compressed_vis = loadmodel->visdata + p; + + for (j=0 ; j<4 ; j++) + out->ambient_sound_level[j] = in->ambient_level[j]; + + #ifndef CLIENTONLY + if (!isDedicated) + #endif + { + // gl underwater warp + if (out->contents != Q1CONTENTS_EMPTY) + { + for (j=0 ; jnummarksurfaces ; j++) + out->firstmarksurface[j]->flags |= SURF_UNDERWATER; + } + if (isnotmap) + { + for (j=0 ; jnummarksurfaces ; j++) + out->firstmarksurface[j]->flags |= SURF_DONTWARP; + } + } + } } - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - loadmodel->leafs = out; - loadmodel->numleafs = count; - - for ( i=0 ; ifileofs); + if (l->filelen % sizeof(*in)) { - out->minmaxs[j] = LittleShort (in->mins[j]); - out->minmaxs[3+j] = LittleShort (in->maxs[j]); + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; } + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); - p = LittleLong(in->contents); - out->contents = p; + loadmodel->leafs = out; + loadmodel->numleafs = count; - out->firstmarksurface = loadmodel->marksurfaces + - (unsigned short)LittleShort(in->firstmarksurface); - out->nummarksurfaces = (unsigned short)LittleShort(in->nummarksurfaces); - - p = LittleLong(in->visofs); - if (p == -1) - out->compressed_vis = NULL; - else - out->compressed_vis = loadmodel->visdata + p; - - for (j=0 ; j<4 ; j++) - out->ambient_sound_level[j] = in->ambient_level[j]; - -#ifndef CLIENTONLY - if (!isDedicated) -#endif + for ( i=0 ; icontents != Q1CONTENTS_EMPTY) + for (j=0 ; j<3 ; j++) { - for (j=0 ; jnummarksurfaces ; j++) - out->firstmarksurface[j]->flags |= SURF_UNDERWATER; + out->minmaxs[j] = LittleShort (in->mins[j]); + out->minmaxs[3+j] = LittleShort (in->maxs[j]); } - if (isnotmap) + + p = LittleLong(in->contents); + out->contents = p; + + out->firstmarksurface = loadmodel->marksurfaces + + (unsigned short)LittleShort(in->firstmarksurface); + out->nummarksurfaces = (unsigned short)LittleShort(in->nummarksurfaces); + + p = LittleLong(in->visofs); + if (p == -1) + out->compressed_vis = NULL; + else + out->compressed_vis = loadmodel->visdata + p; + + for (j=0 ; j<4 ; j++) + out->ambient_sound_level[j] = in->ambient_level[j]; + + #ifndef CLIENTONLY + if (!isDedicated) + #endif { - for (j=0 ; jnummarksurfaces ; j++) - out->firstmarksurface[j]->flags |= SURF_DONTWARP; + // gl underwater warp + if (out->contents != Q1CONTENTS_EMPTY) + { + for (j=0 ; jnummarksurfaces ; j++) + out->firstmarksurface[j]->flags |= SURF_UNDERWATER; + } + if (isnotmap) + { + for (j=0 ; jnummarksurfaces ; j++) + out->firstmarksurface[j]->flags |= SURF_DONTWARP; + } } } - } + } return true; } @@ -2309,21 +2467,36 @@ void RMod_LoadCrouchHull(void) Mod_LoadClipnodes ================= */ -qboolean RMod_LoadClipnodes (lump_t *l) +qboolean RMod_LoadClipnodes (lump_t *l, qboolean lm) { - dclipnode_t *in; + dsclipnode_t *ins; + dsclipnode_t *inl; mclipnode_t *out; int i, count; hull_t *hull; - short cn, c; - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) + if (lm) { - Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); - return false; + ins = NULL; + inl = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*inl)) + { + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*inl); + } + else + { + ins = (void *)(mod_base + l->fileofs); + inl = NULL; + if (l->filelen % sizeof(*ins)) + { + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*ins); } - count = l->filelen / sizeof(*in); out = Hunk_AllocName ( (count+numsuplementryclipnodes)*sizeof(*out), loadname);//space for both loadmodel->clipnodes = out; @@ -2489,33 +2662,22 @@ qboolean RMod_LoadClipnodes (lump_t *l) hull->available = false; } - if (count > 32767) + if (lm) { - /* - if the map contains more than 32767 clipnodes, some of them will overflow - typically this will happen in the second hull, and you thus might not notice it. - - */ - for (i=0 ; iplanenum = LittleLong(in->planenum); - for (c = 0; c < 2; c++) - { - cn = LittleShort(in->children[c]); - if (cn < -10) - out->children[c] = (unsigned short)cn; - else - out->children[c] = cn; - } + out->planenum = LittleLong(inl->planenum); + out->children[0] = LittleLong(inl->children[0]); + out->children[1] = LittleLong(inl->children[1]); } } else { - for (i=0 ; iplanenum = LittleLong(in->planenum); - out->children[0] = LittleShort(in->children[0]); - out->children[1] = LittleShort(in->children[1]); + out->planenum = LittleLong(ins->planenum); + out->children[0] = LittleShort(ins->children[0]); + out->children[1] = LittleShort(ins->children[1]); } } @@ -2532,14 +2694,14 @@ qboolean RMod_LoadClipnodes (lump_t *l) hull->available = true; } - in = suplementryclipnodes; + ins = suplementryclipnodes; - for (i=0 ; iplanenum = LittleLong(in->planenum); - out->children[0] = LittleShort(in->children[0]); + out->planenum = LittleLong(ins->planenum); + out->children[0] = LittleShort(ins->children[0]); out->children[0] += out->children[0]>=0?1:0; - out->children[1] = LittleShort(in->children[1]); + out->children[1] = LittleShort(ins->children[1]); out->children[1] += out->children[1]>=0?1:0; } } @@ -2903,6 +3065,7 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) unsigned int chksum; int start; qboolean noerrors; + qboolean longm = false; #if (defined(ODE_STATIC) || defined(ODE_DYNAMIC)) qboolean ode = true; #else @@ -2931,6 +3094,12 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) loadmodel->fromgame = fg_quake; loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT; } + else if (i == BSPVERSION_LONG) + { + longm = true; + loadmodel->fromgame = fg_quake; + loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT; + } else if (i == BSPVERSIONHL) //halflife support loadmodel->fromgame = fg_halflife; else @@ -2998,7 +3167,7 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) if (!isDedicated || ode) { noerrors = noerrors && RMod_LoadVertexes (&header->lumps[LUMP_VERTEXES]); - noerrors = noerrors && RMod_LoadEdges (&header->lumps[LUMP_EDGES]); + noerrors = noerrors && RMod_LoadEdges (&header->lumps[LUMP_EDGES], longm); noerrors = noerrors && RMod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); } if (!isDedicated) @@ -3014,15 +3183,15 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) if (!isDedicated || ode) { noerrors = noerrors && RMod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); - noerrors = noerrors && RMod_LoadFaces (&header->lumps[LUMP_FACES]); + noerrors = noerrors && RMod_LoadFaces (&header->lumps[LUMP_FACES], longm); } if (!isDedicated) noerrors = noerrors && RMod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]); if (noerrors) RMod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); - noerrors = noerrors && RMod_LoadLeafs (&header->lumps[LUMP_LEAFS]); - noerrors = noerrors && RMod_LoadNodes (&header->lumps[LUMP_NODES]); - noerrors = noerrors && RMod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]); + noerrors = noerrors && RMod_LoadLeafs (&header->lumps[LUMP_LEAFS], longm); + noerrors = noerrors && RMod_LoadNodes (&header->lumps[LUMP_NODES], longm); + noerrors = noerrors && RMod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES], longm); if (noerrors) { RMod_LoadEntities (&header->lumps[LUMP_ENTITIES]); @@ -3179,7 +3348,7 @@ void RMod_FloodFillSkin( qbyte *skin, int skinwidth, int skinheight ) filledcolor = 0; // attempt to find opaque black for (i = 0; i < 256; ++i) - if (d_8to24rgbtable[i] == (255 << 0)) // alpha 1.0 + if (d_8to24rgbtable[i] == (255 << 0)) // rgb 0.0, alpha 1.0 { filledcolor = i; break; @@ -3290,11 +3459,11 @@ void * RMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, pspriteframe->shader = R_RegisterShader(name, "{\n" "{\n" - "map $diffuse\n" - "alphafunc ge128\n" - "depthwrite\n" - "rgbgen entity\n" - "alphagen entity\n" + "map $diffuse\n" + "alphafunc ge128\n" + "depthwrite\n" + "rgbgen vertex\n" + "alphagen vertex\n" "}\n" "}\n" ); diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 804e6c26f..f1421db50 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -127,20 +127,41 @@ m*_t structures are in-memory // entity effects -#define EF_BRIGHTFIELD 1 -#define EF_MUZZLEFLASH 2 -#define EF_BRIGHTLIGHT 4 -#define EF_DIMLIGHT 8 -#define QWEF_FLAG1 16 //only applies to player entities -#define NQEF_NODRAW 16 //so packet entities are free to get this instead -#define QWEF_FLAG2 32 //only applies to player entities -#define NQEF_ADDITIVE 32 //so packet entities are free to get this instead -#define EF_BLUE 64 -#define EF_RED 128 - -#define H2EF_NODRAW 128 //this is going to get complicated... emulated server side. - -#define EF_NODEPTHTEST 8192 //shows through walls. :( +#define EF_BRIGHTFIELD (1<<0) +#define EF_MUZZLEFLASH (1<<1) +#define EF_BRIGHTLIGHT (1<<2) +#define EF_DIMLIGHT (1<<3) +#define QWEF_FLAG1 (1<<4) //only applies to qw player entities +#define NQEF_NODRAW (1<<4) //so packet entities are free to get this instead +#define QWEF_FLAG2 (1<<5) //only applies to qw player entities +#define NQEF_ADDITIVE (1<<5) //so packet entities are free to get this instead +#define EF_BLUE (1<<6) +#define EF_RED (1<<7) +#define H2EF_NODRAW (1<<7) //this is going to get complicated... emulated server side. +#define _DPEF_NOGUNBOB (1<<8) //viewmodel attachment does not bob +#define EF_FULLBRIGHT (1<<9) //abslight=1 +#define _DPEF_FLAME (1<<10) //'onfire' +#define _DPEF_STARDUST (1<<11) //'showering sparks' +#define DPEF_NOSHADOW (1<<12) //doesn't cast a shadow +#define EF_NODEPTHTEST (1<<13) //shows through walls. +#define _DPEF_SELECTABLE (1<<14) //highlights when prydoncursored +#define _DPEF_DOUBLESIDED (1<<15) //disables culling +#define _DPEF_NOSELFSHADOW (1<<16) //doesn't cast shadows on any noselfshadow entities. +#define EF_UNUSED17 (1<<17) +#define EF_UNUSED18 (1<<18) +#define EF_UNUSED19 (1<<19) +#define _DPEF_RESTARTANIM_BIT (1<<20) //exact semantics seems odd +#define _DPEF_TELEPORT_BIT (1<<21) //disable lerping while set +#define DPEF_LOWPRECISION (1<<22) //part of the protocol/server, not the client itself. +#define _DPEF_NOMODELFLAGS (1<<23) +#define EF_MF_ROCKET (1<<24) +#define EF_MF_GRENADE (1<<25) +#define EF_MF_GIB (1<<26) +#define EF_MF_ROTATE (1<<27) +#define EF_MF_TRACER (1<<28) +#define EF_MF_ZOMGIB (1u<<29) +#define EF_MF_TRACER2 (1u<<30) +#define EF_MF_TRACER3 (1u<<31) /* ============================================================================== @@ -764,32 +785,32 @@ typedef struct { typedef enum {mod_brush, mod_sprite, mod_alias, mod_dummy, mod_halflife, mod_heightmap} modtype_t; typedef enum {fg_quake, fg_quake2, fg_quake3, fg_halflife, fg_new, fg_doom, fg_doom3} fromgame_t; //useful when we have very similar model types. (eg quake/halflife bsps) -#define EF_ROCKET 1 // leave a trail -#define EF_GRENADE 2 // leave a trail -#define EF_GIB 4 // leave a trail -#define EF_ROTATE 8 // rotate (bonus items) -#define EF_TRACER 16 // green split trail -#define EF_ZOMGIB 32 // small blood trail -#define EF_TRACER2 64 // orange split trail + rotate -#define EF_TRACER3 128 // purple trail +#define MF_ROCKET 1 // leave a trail +#define MF_GRENADE 2 // leave a trail +#define MF_GIB 4 // leave a trail +#define MF_ROTATE 8 // rotate (bonus items) +#define MF_TRACER 16 // green split trail +#define MF_ZOMGIB 32 // small blood trail +#define MF_TRACER2 64 // orange split trail + rotate +#define MF_TRACER3 128 // purple trail //hexen2 support. -#define EFH2_FIREBALL 256 // Yellow transparent trail in all directions -#define EFH2_ICE 512 // Blue-white transparent trail, with gravity -#define EFH2_MIP_MAP 1024 // This model has mip-maps -#define EFH2_SPIT 2048 // Black transparent trail with negative light -#define EFH2_TRANSPARENT 4096 // Transparent sprite -#define EFH2_SPELL 8192 // Vertical spray of particles -#define EFH2_HOLEY 16384 // Solid model with color 0 -#define EFH2_SPECIAL_TRANS 32768 // Translucency through the particle table -#define EFH2_FACE_VIEW 65536 // Poly Model always faces you -#define EFH2_VORP_MISSILE 131072 // leave a trail at top and bottom of model -#define EFH2_SET_STAFF 262144 // slowly move up and left/right -#define EFH2_MAGICMISSILE 524288 // a trickle of blue/white particles with gravity -#define EFH2_BONESHARD 1048576 // a trickle of brown particles with gravity -#define EFH2_SCARAB 2097152 // white transparent particles with little gravity -#define EFH2_ACIDBALL 4194304 // Green drippy acid shit -#define EFH2_BLOODSHOT 8388608 // Blood rain shot trail +#define MFH2_FIREBALL 256 // Yellow transparent trail in all directions +#define MFH2_ICE 512 // Blue-white transparent trail, with gravity +#define MFH2_MIP_MAP 1024 // This model has mip-maps +#define MFH2_SPIT 2048 // Black transparent trail with negative light +#define MFH2_TRANSPARENT 4096 // Transparent sprite +#define MFH2_SPELL 8192 // Vertical spray of particles +#define MFH2_HOLEY 16384 // Solid model with color 0 +#define MFH2_SPECIAL_TRANS 32768 // Translucency through the particle table +#define MFH2_FACE_VIEW 65536 // Poly Model always faces you +#define MFH2_VORP_MISSILE 131072 // leave a trail at top and bottom of model +#define MFH2_SET_STAFF 262144 // slowly move up and left/right +#define MFH2_MAGICMISSILE 524288 // a trickle of blue/white particles with gravity +#define MFH2_BONESHARD 1048576 // a trickle of brown particles with gravity +#define MFH2_SCARAB 2097152 // white transparent particles with little gravity +#define MFH2_ACIDBALL 4194304 // Green drippy acid shit +#define MFH2_BLOODSHOT 8388608 // Blood rain shot trail typedef union { struct { @@ -950,7 +971,7 @@ qboolean Heightmap_Edit(model_t *mod, int action, float *pos, float radius, floa void CM_InitBoxHull (void); #ifdef __cplusplus -//#pragma message (" c++ stinks") +//#pragma warningmsg (" c++ stinks") #else void CM_Init(void); diff --git a/engine/gl/gl_ngraph.c b/engine/gl/gl_ngraph.c index 004f15b07..5fd25d4aa 100644 --- a/engine/gl/gl_ngraph.c +++ b/engine/gl/gl_ngraph.c @@ -20,12 +20,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // gl_ngraph.c #include "quakedef.h" -#ifdef GLQUAKE -#include "glquake.h" +#include "shader.h" extern qbyte *draw_chars; // 8*8 graphic characters -texid_t netgraphtexture; // netgraph texture +static texid_t netgraphtexture; // netgraph texture +static shader_t *netgraphshader; #define NET_GRAPHHEIGHT 32 @@ -61,13 +61,16 @@ static void R_LineGraph (int x, int h) ngraph_texels[NET_GRAPHHEIGHT - i - 1][x] = (qbyte)0xff; } -void Draw_CharToNetGraph (int x, int y, int num) +static void Draw_CharToNetGraph (int x, int y, int num) { int row, col; qbyte *source; int drawline; int nx; + if (!draw_chars) + return; + row = num>>4; col = num&15; source = draw_chars + (row<<10) + (col<<3); @@ -118,30 +121,9 @@ void GLR_NetGraph (void) Draw_FunString(8, y, st); y += 8; -#ifndef ANDROID - GL_MTBind(0, GL_TEXTURE_2D, netgraphtexture); - - qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, - NET_TIMINGS, NET_GRAPHHEIGHT, 0, GL_RGBA, - GL_UNSIGNED_BYTE, ngraph_pixels); - - GL_TexEnv(GL_MODULATE); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - x = 8; - qglColor3f (1,1,1); - qglBegin (GL_QUADS); - qglTexCoord2f (0, 0); - qglVertex2f (x, y); - qglTexCoord2f (1, 0); - qglVertex2f (x+NET_TIMINGS, y); - qglTexCoord2f (1, 1); - qglVertex2f (x+NET_TIMINGS, y+NET_GRAPHHEIGHT); - qglTexCoord2f (0, 1); - qglVertex2f (x, y+NET_GRAPHHEIGHT); - qglEnd (); -#endif + R_Upload(netgraphtexture, "***netgraph***", TF_RGBA32, ngraph_pixels, NULL, NET_TIMINGS, NET_GRAPHHEIGHT, IF_NOMIPMAP|IF_NOPICMIP); + x=8; + R2D_Image(x, y, NET_TIMINGS, NET_GRAPHHEIGHT, 0, 0, 1, 1, netgraphshader); } void GLR_FrameTimeGraph (int frametime) @@ -180,30 +162,21 @@ void GLR_FrameTimeGraph (int frametime) Draw_FunString(8, y, st); y += 8; -#ifndef ANDROID - GL_MTBind(0, GL_TEXTURE_2D, netgraphtexture); - - qglTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, - NET_TIMINGS, NET_GRAPHHEIGHT, 0, GL_RGBA, - GL_UNSIGNED_BYTE, ngraph_pixels); - - GL_TexEnv(GL_MODULATE); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - x = 8; - qglColor3f (1,1,1); - qglBegin (GL_QUADS); - qglTexCoord2f (0, 0); - qglVertex2f (x, y); - qglTexCoord2f (1, 0); - qglVertex2f (x+NET_TIMINGS, y); - qglTexCoord2f (1, 1); - qglVertex2f (x+NET_TIMINGS, y+NET_GRAPHHEIGHT); - qglTexCoord2f (0, 1); - qglVertex2f (x, y+NET_GRAPHHEIGHT); - qglEnd (); -#endif + R_Upload(netgraphtexture, "***netgraph***", TF_RGBA32, ngraph_pixels, NULL, NET_TIMINGS, NET_GRAPHHEIGHT, IF_NOMIPMAP|IF_NOPICMIP); + x=8; + R2D_Image(x, y, NET_TIMINGS, NET_GRAPHHEIGHT, 0, 0, 1, 1, netgraphshader); } -#endif +void R_NetgraphInit(void) +{ + TEXASSIGN(netgraphtexture, GL_AllocNewTexture("***netgraph***", NET_TIMINGS, NET_GRAPHHEIGHT)); + netgraphshader = R_RegisterShader("netgraph", + "{\n" + "{\n" + "map $diffuse\n" + "blendfunc blend\n" + "}\n" + "}\n" + ); + netgraphshader->defaulttextures.base = netgraphtexture; +} diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 7d5e313ee..5431bb1c7 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -24,6 +24,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "glquake.h" #include "shader.h" +extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_lightmaps; + int r_dlightframecount; int d_lightstylevalue[256]; // 8.8 fraction of base light value @@ -97,9 +99,9 @@ void AddLightBlend (float r, float g, float b, float a2) //Con_Printf("AddLightBlend(): %4.2f %4.2f %4.2f %4.6f\n", v_blend[0], v_blend[1], v_blend[2], v_blend[3]); } -float bubble_sintable[17], bubble_costable[17]; +static float bubble_sintable[17], bubble_costable[17]; -void R_InitBubble(void) +static void R_InitBubble(void) { float a; int i; @@ -157,7 +159,7 @@ void R_InitFlashblends(void) flashblend_shader = R_RegisterShader("flashblend", "{\n" "{\n" - "map $whitetexture\n" + "map %whiteimage\n" "blendfunc gl_one gl_one\n" "rgbgen vertex\n" "alphagen vertex\n" @@ -165,6 +167,8 @@ void R_InitFlashblends(void) "}\n" ); lpplight_shader = NULL; + + R_InitBubble(); } static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expand) @@ -205,7 +209,7 @@ static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expa flashblend_colours[0][3] = 1; VectorCopy(light->origin, flashblend_vcoords[0]); - for (i=16 ; i>0 ; i--) + for (i=FLASHBLEND_VERTS ; i>0 ; i--) { for (j=0 ; j<3 ; j++) flashblend_vcoords[i][j] = light->origin[j] + (vright[j]*(*bub_cos) + @@ -220,7 +224,7 @@ static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expa vec3_t diff; VectorSubtract(r_origin, light->origin, diff); VectorNormalize(diff); - for (i=0 ; i<=16 ; i++) + for (i=0 ; i<=FLASHBLEND_VERTS ; i++) VectorMA(flashblend_vcoords[i], rad, diff, flashblend_vcoords[i]); } return true; @@ -231,7 +235,7 @@ static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expa R_RenderDlights ============= */ -void GLR_RenderDlights (void) +void R_RenderDlights (void) { int i; dlight_t *l; @@ -376,6 +380,12 @@ void R_PushDlights (void) r_dlightframecount = r_framecount + 1; // because the count hasn't // advanced yet for this frame +#ifdef RTLIGHTS + /*if we're doing full rtlighting only, then don't bother calculating old-style dlights as they won't be visible anyway*/ + if (r_shadow_realtime_world.value && r_shadow_realtime_world_lightmaps.value < 0.1) + return; +#endif + if (!r_dynamic.ival || !cl.worldmodel) return; @@ -509,9 +519,14 @@ void GLQ3_LightGrid(model_t *mod, vec3_t point, vec3_t res_diffuse, vec3_t res_a direction_uv[j] = anglemod ( direction_uv[j] ); } + VectorScale(ambient, 4, ambient); + VectorScale(diffuse, 4, diffuse); + + /*ambient is the min level*/ + /*diffuse is the max level*/ VectorCopy(ambient, res_ambient); if (res_diffuse) - VectorCopy(diffuse, res_diffuse); + VectorAdd(diffuse, ambient, res_diffuse); if (res_dir) { vec3_t right, left; diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 9f43f875a..4afc97a43 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -107,93 +107,27 @@ texid_t sceneblur_texture; texid_t scenepp_texture_warp; texid_t scenepp_texture_edge; -int scenepp_mt_program; -int scenepp_mt_parm_texture0i; -int scenepp_mt_parm_colorf; -int scenepp_mt_parm_inverti; - -texid_t scenepp_fisheye_texture; -int scenepp_fisheye_program; -int scenepp_fisheye_parm_fov; -int scenepp_panorama_program; -int scenepp_panorama_parm_fov; +texid_t scenepp_postproc_cube; // KrimZon - init post processing - called in GL_CheckExtensions, when they're called // I put it here so that only this file need be changed when messing with the post // processing shaders void GL_InitSceneProcessingShaders_WaterWarp (void) { - /* - inputs: - texcoords: edge points - coords: vertex coords (duh) - time - ampscale (cvar = r_waterwarp) - - use ifs instead of an edge map? - */ if (gl_config.arb_shader_objects) { scenepp_waterwarp = R_RegisterShader("waterwarp", "{\n" - "glslprogram\n" - "{\n" - "#ifdef VERTEX_SHADER\n" - "\ - attribute vec2 v_texcoord;\ - varying vec2 v_stc;\ - varying vec2 v_warp;\ - varying vec2 v_edge;\ - uniform float e_time;\ - void main (void)\ - {\ - gl_Position = ftetransform();\ - v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0;\ - v_warp.s = e_time * 0.25 + v_texcoord.s;\ - v_warp.t = e_time * 0.25 + v_texcoord.t;\ - v_edge = v_texcoord.xy;\ - }\ - \n" - "#endif\n" - "#ifdef FRAGMENT_SHADER\n" - "\ - varying vec2 v_stc;\ - varying vec2 v_warp;\ - varying vec2 v_edge;\ - uniform sampler2D s_t0;\ - uniform sampler2D s_t1;\ - uniform sampler2D s_t2;\ - uniform float ampscale;\ - uniform vec3 rendertexturescale;\ - void main (void)\ - {\ - float amptemp;\ - vec3 edge;\ - edge = texture2D( s_t2, v_edge ).rgb;\ - amptemp = (0.010 / 0.625) * ampscale * edge.x;\ - vec3 offset;\ - offset = texture2D( s_t1, v_warp ).rgb;\ - offset.x = (offset.x - 0.5) * 2.0;\ - offset.y = (offset.y - 0.5) * 2.0;\ - vec2 temp;\ - temp.x = v_stc.x + offset.x * amptemp;\ - temp.y = v_stc.y + offset.y * amptemp;\ - gl_FragColor = texture2D( s_t0, temp*rendertexturescale.st );\ - }\ - \n" - "#endif\n" - "}\n" - "param cvarf r_waterwarp ampscale\n" - "param rendertexturescale rendertexturescale\n" - "{\n" - "map $currentrender\n" - "}\n" - "{\n" - "map $upperoverlay\n" - "}\n" - "{\n" - "map $loweroverlay\n" - "}\n" + "program underwaterwarp\n" + "{\n" + "map $currentrender\n" + "}\n" + "{\n" + "map $upperoverlay\n" + "}\n" + "{\n" + "map $loweroverlay\n" + "}\n" "}\n" ); scenepp_waterwarp->defaulttextures.upperoverlay = scenepp_texture_warp; @@ -201,76 +135,11 @@ void GL_InitSceneProcessingShaders_WaterWarp (void) } } -void GL_InitFisheyeFov(void) -{ - char *vshader = "\ - varying vec2 texcoord;\ - void main(void)\ - {\ - texcoord = gl_MultiTexCoord0.xy;\ - gl_Position = ftetransform();\ - }"; - char *fisheyefshader = "\ - uniform samplerCube source;\ - varying vec2 texcoord;\ - uniform float fov;\ - void main(void)\ - {\ - vec3 tc; \ - vec2 d; \ - vec2 ang; \ - d = texcoord; \ - ang.x = sqrt(d.x*d.x+d.y*d.y)*fov; \ - ang.y = -atan(d.y, d.x); \ - tc.x = sin(ang.x) * cos(ang.y); \ - tc.y = sin(ang.x) * sin(ang.y); \ - tc.z = cos(ang.x); \ - gl_FragColor = textureCube(source, tc);\ - }"; - - char *panoramafshader = "\ - uniform samplerCube source;\ - varying vec2 texcoord;\ - uniform float fov;\ - void main(void)\ - {\ - vec3 tc; \ - float ang; \ - ang = texcoord.x*fov; \ - tc.x = sin(ang); \ - tc.y = -texcoord.y; \ - tc.z = cos(ang); \ - gl_FragColor = textureCube(source, tc);\ - }"; - - if (gl_config.gles) - return; - - scenepp_fisheye_program = GLSlang_CreateProgram("fisheye", "#version 110\n", NULL, vshader, fisheyefshader); - if (scenepp_fisheye_program) - { - GLSlang_UseProgram(scenepp_fisheye_program); - GLSlang_SetUniform1i(GLSlang_GetUniformLocation(scenepp_fisheye_program, "source"), 0); - scenepp_fisheye_parm_fov = GLSlang_GetUniformLocation(scenepp_fisheye_program, "fov"); - GLSlang_UseProgram(0); - } - - scenepp_panorama_program = GLSlang_CreateProgram("panorama", "#version 110\n", NULL, vshader, panoramafshader); - if (scenepp_panorama_program) - { - GLSlang_UseProgram(scenepp_panorama_program); - GLSlang_SetUniform1i(GLSlang_GetUniformLocation(scenepp_panorama_program, "source"), 0); - scenepp_panorama_parm_fov = GLSlang_GetUniformLocation(scenepp_panorama_program, "fov"); - GLSlang_UseProgram(0); - } -} - void GL_InitSceneProcessingShaders (void) { if (gl_config.arb_shader_objects) { GL_InitSceneProcessingShaders_WaterWarp(); - GL_InitFisheyeFov(); } } @@ -283,15 +152,15 @@ void GL_SetupSceneProcessingTextures (void) unsigned char pp_warp_tex[PP_WARP_TEX_SIZE*PP_WARP_TEX_SIZE*3]; unsigned char pp_edge_tex[PP_AMP_TEX_SIZE*PP_AMP_TEX_SIZE*3]; - scenepp_fisheye_texture = r_nulltex; + scenepp_postproc_cube = r_nulltex; - sceneblur_texture = GL_AllocNewTexture(0, 0); + TEXASSIGN(sceneblur_texture, GL_AllocNewTexture("***postprocess_blur***", 0, 0)); if (!gl_config.arb_shader_objects) return; - scenepp_texture_warp = GL_AllocNewTexture(0, 0); - scenepp_texture_edge = GL_AllocNewTexture(0, 0); + TEXASSIGN(scenepp_texture_warp, GL_AllocNewTexture("***postprocess_warp***", 0, 0)); + TEXASSIGN(scenepp_texture_edge, GL_AllocNewTexture("***postprocess_edge***", 0, 0)); // init warp texture - this specifies offset in for (y=0; yaxis[0][0]; m[1] = e->axis[0][1]; m[2] = e->axis[0][2]; @@ -594,6 +461,12 @@ void R_RenderScene (void) RQ_BeginFrame(); + if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) + { + TRACE(("dbg: calling R_DrawParticles\n")); + P_DrawParticles (); + } + if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) { TRACE(("dbg: calling R_DrawWorld\n")); @@ -607,13 +480,8 @@ void R_RenderScene (void) // R_DrawDecals(); TRACE(("dbg: calling R_RenderDlights\n")); - GLR_RenderDlights (); + R_RenderDlights (); - if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) - { - TRACE(("dbg: calling R_DrawParticles\n")); - P_DrawParticles (); - } RQ_RenderBatchClear(); cl_numvisedicts = tmpvisents; @@ -867,8 +735,8 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist) GL_CullFace(0); -#ifdef _MSC_VER -#pragma message("warning: there's a bug with rtlights in portals, culling is broken or something. May also be loading the wrong matrix") +#ifdef warningmsg +#pragma warningmsg("warning: there's a bug with rtlights in portals, culling is broken or something. May also be loading the wrong matrix") #endif } @@ -956,12 +824,10 @@ static void R_RenderMotionBlur(void) { int vwidth = 1, vheight = 1; float vs, vt, cs, ct; -#ifdef _MSC_VER -#pragma message("backend fixme") +#ifdef warningmsg +#pragma warningmsg("backend fixme") #endif #ifndef ANDROID - Con_Printf("motionblur is not updated for the backend\n"); - if (gl_config.arb_texture_non_power_of_two) { //we can use any size, supposedly vwidth = vid.pixelwidth; @@ -1027,9 +893,8 @@ static void R_RenderMotionBlur(void) PPL_RevertToKnownState(); } -#ifdef FISH /*FIXME: we could use geometry shaders to draw to all 6 faces at once*/ -qboolean R_RenderScene_Fish(void) +qboolean R_RenderScene_Cubemap(void) { int cmapsize = 512; int i; @@ -1037,22 +902,67 @@ qboolean R_RenderScene_Fish(void) { {0, -90, 0}, {0, 90, 0}, {90, 0, 0}, {-90, 0, 0}, {0, 0, 0}, {0, -180, 0} }; - int order[6] = {4, 0, 1, 5, 3, 2}; - int numsides = 4; vec3_t saveang; vrect_t vrect; vrect_t prect; + shader_t *shader; + int facemask; + + /*needs glsl*/ + if (!gl_config.arb_shader_objects) + return false; + if (!ffov.value) + return false; + + facemask = 0; + if (ffov.value < 0) + { + shader = R_RegisterShader("postproc_panorama", + "{\n" + "program postproc_panorama\n" + "{\n" + "map $sourcecube\n" + "}\n" + "}\n" + ); + + //panoramic view needs at most the four sides + facemask |= 1<<4; /*front view*/ + if (ffov.value < -90) + { + facemask |= (1<<0) | (1<<1); /*side views*/ + if (ffov.value < -270) + facemask |= 1<<5; /*back view*/ + } + } + else + { + shader = R_RegisterShader("postproc_fisheye", + "{\n" + "program postproc_fisheye\n" + "{\n" + "map $sourcecube\n" + "}\n" + "}\n" + ); + + //fisheye view sees up to a full sphere + facemask |= 1<<4; /*front view*/ + if (ffov.value > 77) + facemask |= (1<<0) | (1<<1) | (1<<2) | (1<<3); /*side/top/bottom views*/ + if (ffov.value > 270) + facemask |= 1<<5; /*back view*/ + } + +//fixme: should already have the vrect somewhere. SCR_VRectForPlayer(&vrect, r_refdef.currentplayernum); prect.x = (vrect.x * vid.pixelwidth)/vid.width; prect.width = (vrect.width * vid.pixelwidth)/vid.width; prect.y = (vrect.y * vid.pixelheight)/vid.height; prect.height = (vrect.height * vid.pixelheight)/vid.height; - if (!scenepp_panorama_program) - return false; - if (gl_config.arb_texture_non_power_of_two) { if (prect.width < prect.height) @@ -1071,67 +981,17 @@ qboolean R_RenderScene_Fish(void) VectorCopy(r_refdef.viewangles, saveang); saveang[2] = 0; - if (ffov.value < 0) + if (!TEXVALID(scenepp_postproc_cube)) { - //panoramic view needs at most the four sides - if (ffov.value >= -90) - numsides = 1; -// else if (ffov.value >= -180) -// { -// numsides = 2; -// rot45 = 1; -// } - else if (ffov.value >= -270) - numsides = 3; - else - numsides = 4; + scenepp_postproc_cube = GL_AllocNewTexture("***fish***", cmapsize, cmapsize); - order[0] = 4; - order[1] = 0; - order[2] = 1; - order[3] = 5; - } - else - { - //fisheye view sees a full sphere - // - if (ffov.value <= 77) - numsides = 1; -// else if (ffov.value <= 180) -// { -// numsides = 3; -// rot45 = 3; -// } - else if (ffov.value <= 270) - numsides = 5; - else - numsides = 6; - - order[0] = 4; - order[1] = 0; - order[2] = 3; - order[3] = 1; - order[4] = 2; - order[5] = 5; - } - - if (!TEXVALID(scenepp_fisheye_texture)) - { - scenepp_fisheye_texture = GL_AllocNewTexture(cmapsize, cmapsize); - - qglDisable(GL_TEXTURE_2D); - qglEnable(GL_TEXTURE_CUBE_MAP_ARB); - - GL_MTBind(0, GL_TEXTURE_CUBE_MAP_ARB, scenepp_fisheye_texture); + GL_MTBind(0, GL_TEXTURE_CUBE_MAP_ARB, scenepp_postproc_cube); for (i = 0; i < 6; i++) qglCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, 0, GL_RGB, 0, 0, cmapsize, cmapsize, 0); qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - qglEnable(GL_TEXTURE_2D); - qglDisable(GL_TEXTURE_CUBE_MAP_ARB); } r_refdef.vrect.width = cmapsize; @@ -1147,44 +1007,30 @@ qboolean R_RenderScene_Fish(void) ang[1][1] = 90; ang[1][2] = saveang[0]; ang[5][0] = -saveang[0]*2; - for (i = 0; i < numsides; i++) + for (i = 0; i < 6; i++) { + if (!(facemask & (1<name, fname, sizeof(fname)); strncat(fname, ".rtlights", MAX_QPATH-1); @@ -861,21 +862,22 @@ static void R_SaveRTLights_f(void) continue; if (!light->radius) continue; + VectorAngles(light->axis[0], light->axis[2], ang); VFS_PUTS(f, va( "%s%f %f %f " "%f %f %f %f " "%i " "\"%s\" %f " "%f %f %f " - "%f %f %f %i " + "%f %f %f %f %i " "\n" , (light->flags & LFLAG_NOSHADOWS)?"!":"", light->origin[0], light->origin[1], light->origin[2], light->radius, light->color[0], light->color[1], light->color[2], light->style-1, - "", 0.0f, - 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, light->flags&(LFLAG_NORMALMODE|LFLAG_REALTIMEMODE) + "", light->corona, + ang[0], ang[1], ang[2], + light->coronascale, light->ambientscale, light->diffusescale, light->specularscale, light->flags&(LFLAG_NORMALMODE|LFLAG_REALTIMEMODE) )); } VFS_CLOSE(f); @@ -970,6 +972,7 @@ TRACE(("dbg: GLR_NewMap: tp\n")); void GLR_PreNewMap(void) { + r_loadbumpmapping = r_deluxemapping.ival || r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival; } diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index bfa9bf470..2432f7dd5 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -26,9 +26,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "renderque.h" #include -extern cvar_t gl_bump; - - void GLBE_ClearVBO(vbo_t *vbo) { int vboh[7]; @@ -327,7 +324,7 @@ void GLBE_UploadAllLightmaps(void) lightmap[i]->lightmaps); break; } - if (gl_bump.ival) + if (r_deluxemapping.ival) { lightmap[i]->deluxmodified = false; lightmap[i]->deluxrectchange.l = LMBLOCK_WIDTH; diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index fe7e53bbc..79713aaac 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -37,6 +37,7 @@ extern LPDIRECT3DDEVICE9 pD3DDev9; #endif extern texid_t missing_texture; +static texid_t r_whiteimage; static qboolean shader_reload_needed; static qboolean shader_rescan_needed; @@ -221,18 +222,17 @@ static qboolean Shader_EvaluateCondition(char **ptr) } if (*token == '$') { - extern cvar_t gl_bump; token++; if (!Q_stricmp(token, "lpp")) conditiontrue = conditiontrue == !r_lightprepass.ival; else if (!Q_stricmp(token, "lightmap")) conditiontrue = conditiontrue == !r_fullbright.value; else if (!Q_stricmp(token, "deluxmap") ) - conditiontrue = conditiontrue == (r_deluxemapping.value && gl_bump.value); + conditiontrue = conditiontrue == r_deluxemapping.ival; //normalmaps are generated if they're not already known. else if (!Q_stricmp(token, "normalmap") ) - conditiontrue = conditiontrue == !!gl_bump.value; + conditiontrue = conditiontrue == r_loadbumpmapping; else if (!Q_stricmp(token, "gles") ) { @@ -265,13 +265,14 @@ static qboolean Shader_EvaluateCondition(char **ptr) #else conditiontrue = conditiontrue == false; #endif - } + // GCC hates these within if statements "error: expected '}' before 'else'" -#ifdef _MSC_VER -#pragma message("shader fixme") +#ifdef warningmsg +#pragma warningmsg("shader fixme") #endif + } else if (!Q_stricmp(token, "diffuse") ) conditiontrue = conditiontrue == true; else if (!Q_stricmp(token, "specular") ) @@ -548,7 +549,7 @@ static int Shader_SetImageFlags ( shader_t *shader ) static texid_t Shader_FindImage ( char *name, int flags ) { if (!Q_stricmp (name, "$whiteimage")) - return r_nulltex; + return r_whiteimage; else return R_LoadHiResTexture(name, NULL, flags); } @@ -775,7 +776,6 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i unsigned int nopermutation = ~0u; int p, n, pn; char *end; - char *vers; char *cvarfnames[64]; int cvarfcount = 0; @@ -829,10 +829,6 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i break; }; - if (ver) - vers = va("#version %u\n", ver); - else - vers = NULL; memset(prog->handle, 0, sizeof(*prog->handle)*PERMUTATIONS); for (p = 0; p < PERMUTATIONS; p++) { @@ -853,7 +849,7 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i permutationdefines[pn++] = permutationname[n]; } permutationdefines[pn++] = NULL; - prog->handle[p].glsl = GLSlang_CreateProgram(name, vers, permutationdefines, script, script); + prog->handle[p].glsl = GLSlang_CreateProgram(name, (((p & PERMUTATION_SKELETAL) && ver < 120)?120:ver), permutationdefines, script, script); } #endif #ifdef D3DQUAKE @@ -905,11 +901,10 @@ struct sbuiltin_s /*defaultfill is a simple shader for block-filling with vertex colours. note that the blendfunc stuff is done after the shader anyway.*/ {QR_OPENGL/*ES*/, 100, "defaultfill", "#ifdef VERTEX_SHADER\n" - "attribute vec2 v_texcoord;\n" "attribute vec4 v_colour;\n" "varying vec4 vc;\n" - "void main (void)\n" + "void main ()\n" "{\n" " vc = v_colour;\n" " gl_Position = ftetransform();\n" @@ -918,7 +913,7 @@ struct sbuiltin_s "#ifdef FRAGMENT_SHADER\n" "varying lowp vec4 vc;\n" - "void main (void)\n" + "void main ()\n" "{\n" " gl_FragColor = vc;\n" "}\n" @@ -932,7 +927,7 @@ struct sbuiltin_s "varying vec2 tc;\n" "varying vec4 vc;\n" - "void main (void)\n" + "void main ()\n" "{\n" " tc = v_texcoord;\n" " vc = v_colour;\n" @@ -945,7 +940,7 @@ struct sbuiltin_s "varying mediump vec2 tc;\n" "varying lowp vec4 vc;\n" - "void main (void)\n" + "void main ()\n" "{\n" " gl_FragColor = texture2D(s_t0, tc) * vc;\n" "}\n" @@ -958,7 +953,7 @@ struct sbuiltin_s "varying vec2 tc;\n" "varying vec4 vc;\n" - "void main (void)\n" + "void main ()\n" "{\n" " tc = v_texcoord;\n" " vc = v_colour;\n" @@ -971,7 +966,7 @@ struct sbuiltin_s "in vec2 tc;\n" "varying vec4 vc;\n" - "void main (void)\n" + "void main ()\n" "{\n" " gl_FragColor = texture2D(s_t0, tc) * vc;\n" "}\n" @@ -985,7 +980,7 @@ struct sbuiltin_s "attribute vec2 v_lmcoord;\n" "varying vec2 tc, lm;\n" - "void main (void)\n" + "void main ()\n" "{\n" " tc = v_texcoord;\n" " lm = v_lmcoord;\n" @@ -1002,7 +997,7 @@ struct sbuiltin_s "varying mediump vec2 tc, lm;\n" "uniform mediump float cvar_gl_overbright;\n" - "void main (void)\n" + "void main ()\n" "{\n" " mediump float scale = exp2(floor(clamp(cvar_gl_overbright, 0.0, 2.0)));\n" " gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * vec4(scale, scale, scale, 1);\n" @@ -1016,7 +1011,7 @@ struct sbuiltin_s "attribute vec2 v_lmcoord;\n" "varying vec2 tc, lm;\n" - "void main (void)\n" + "void main ()\n" "{\n" " tc = v_texcoord;\n" " lm = v_lmcoord;\n" @@ -1033,7 +1028,7 @@ struct sbuiltin_s "varying vec2 tc, lm;\n" "uniform float cvar_gl_overbright;\n" - "void main (void)\n" + "void main ()\n" "{\n" " float scale = exp2(floor(clamp(cvar_gl_overbright, 0.0, 2.0)));\n" " gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * vec4(scale, scale, scale, 1);\n" @@ -1046,7 +1041,7 @@ struct sbuiltin_s "varying mediump vec2 tc;\n" "#ifdef VERTEX_SHADER\n" "attribute vec2 v_texcoord;\n" - "void main (void)\n" + "void main ()\n" "{\n" " tc = v_texcoord;\n" " gl_Position = ftetransform();\n" @@ -1058,7 +1053,7 @@ struct sbuiltin_s "uniform mediump float e_time;\n" "uniform lowp float cvar_r_wateralpha;\n" - "void main (void)\n" + "void main ()\n" "{\n" " mediump vec2 ntc;\n" " ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n" @@ -1074,7 +1069,7 @@ struct sbuiltin_s "varying vec2 tc;\n" "#ifdef VERTEX_SHADER\n" "attribute vec2 v_texcoord;\n" - "void main (void)\n" + "void main ()\n" "{\n" " tc = v_texcoord.st;\n" " gl_Position = ftetransform();\n" @@ -1086,7 +1081,7 @@ struct sbuiltin_s "uniform float e_time;\n" "uniform float cvar_r_wateralpha;\n" - "void main (void)\n" + "void main ()\n" "{\n" " vec2 ntc;\n" " ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n" @@ -1097,12 +1092,122 @@ struct sbuiltin_s "}\n" "#endif\n" }, + {QR_OPENGL, 110, "underwaterwarp", + /* + inputs: + texcoords: edge points + coords: vertex coords (duh) + time + ampscale (cvar = r_waterwarp) + + use ifs instead of an edge map? + */ + "!!cvarf r_waterwarp\n" + "#ifdef VERTEX_SHADER\n" + "attribute vec2 v_texcoord;\n" + "varying vec2 v_stc;\n" + "varying vec2 v_warp;\n" + "varying vec2 v_edge;\n" + "uniform float e_time;\n" + "void main ()\n" + "{\n" + "gl_Position = ftetransform();\n" + "v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0;\n" + "v_warp.s = e_time * 0.25 + v_texcoord.s;\n" + "v_warp.t = e_time * 0.25 + v_texcoord.t;\n" + "v_edge = v_texcoord.xy;\n" + "}\n" + "#endif\n" + "#ifdef FRAGMENT_SHADER\n" + "varying vec2 v_stc;\n" + "varying vec2 v_warp;\n" + "varying vec2 v_edge;\n" + "uniform sampler2D s_t0;/*$currentrender*/\n" + "uniform sampler2D s_t1;/*warp image*/\n" + "uniform sampler2D s_t2;/*edge image*/\n" + "uniform vec3 e_rendertexturescale;\n" + "uniform float cvar_r_waterwarp;\n" + "void main ()\n" + "{\n" + "float amptemp;\n" + "vec3 edge;\n" + "edge = texture2D( s_t2, v_edge ).rgb;\n" + "amptemp = (0.010 / 0.625) * cvar_r_waterwarp * edge.x;\n" + "vec3 offset;\n" + "offset = texture2D( s_t1, v_warp ).rgb;\n" + "offset.x = (offset.x - 0.5) * 2.0;\n" + "offset.y = (offset.y - 0.5) * 2.0;\n" + "vec2 temp;\n" + "temp.x = v_stc.x + offset.x * amptemp;\n" + "temp.y = v_stc.y + offset.y * amptemp;\n" + "gl_FragColor = texture2D( s_t0, temp*e_rendertexturescale.st );\n" + "}\n" + "#endif\n" + }, + {QR_OPENGL, 110, "postproc_panorama", + "!!cvarf ffov\n" + "#ifdef VERTEX_SHADER\n" + "attribute vec2 v_texcoord;\n" + "varying vec2 texcoord;\n" + "void main()\n" + "{\n" + "texcoord = v_texcoord.xy;\n" + "gl_Position = ftetransform();\n" + "}\n" + "#endif\n" + "#ifdef FRAGMENT_SHADER\n" + "uniform samplerCube s_t0;\n" + "varying vec2 texcoord;\n" + "uniform float cvar_ffov;\n" + "void main()\n" + "{\n" + "vec3 tc; \n" + "float ang; \n" + "ang = texcoord.x*-radians(cvar_ffov); \n" + "tc.x = sin(ang); \n" + "tc.y = -texcoord.y; \n" + "tc.z = cos(ang); \n" + "gl_FragColor = textureCube(s_t0, tc);\n" + "}\n" + "#endif\n" + + }, + {QR_OPENGL, 110, "postproc_fisheye", + "!!cvarf ffov\n" + "#ifdef VERTEX_SHADER\n" + "attribute vec2 v_texcoord;\n" + "varying vec2 texcoord;\n" + "void main()\n" + "{\n" + "texcoord = v_texcoord.xy;\n" + "gl_Position = ftetransform();\n" + "}\n" + "#endif\n" + "#ifdef FRAGMENT_SHADER\n" + "uniform samplerCube s_t0;\n" + "varying vec2 texcoord;\n" + "uniform float cvar_ffov;\n" + "void main()\n" + "{\n" + "vec3 tc; \n" + "vec2 d; \n" + "vec2 ang; \n" + "d = texcoord; \n" + "ang.x = sqrt(d.x*d.x+d.y*d.y)*radians(cvar_ffov); \n" + "ang.y = -atan(d.y, d.x); \n" + "tc.x = sin(ang.x) * cos(ang.y); \n" + "tc.y = sin(ang.x) * sin(ang.y); \n" + "tc.z = cos(ang.x); \n" + "gl_FragColor = textureCube(s_t0, tc);\n" + "}\n" + "#endif\n" + }, /*defautsky projects the texture in order to match q1 skies, along with two separate layers scrolling at separate speeds*/ {QR_OPENGL/*ES*/, 100, "defaultsky", "#ifdef VERTEX_SHADER\n" "varying vec3 pos;\n" - "void main (void)\n" + "void main ()\n" "{\n" " pos = v_position.xyz;\n" " gl_Position = ftetransform();\n" @@ -1117,7 +1222,7 @@ struct sbuiltin_s "uniform mediump vec3 e_eyepos;\n" "varying mediump vec3 pos;\n" - "void main (void)\n" + "void main ()\n" "{\n" " mediump vec2 tccoord;\n" @@ -1141,7 +1246,7 @@ struct sbuiltin_s "#ifdef VERTEX_SHADER\n" "varying vec3 pos;\n" - "void main (void)\n" + "void main ()\n" "{\n" " pos = v_position.xyz;\n" " gl_Position = ftetransform();\n" @@ -1155,7 +1260,7 @@ struct sbuiltin_s "uniform sampler2D s_t0;\n" "uniform sampler2D s_t1;\n" - "void main (void)\n" + "void main ()\n" "{\n" " vec2 tccoord;\n" @@ -1181,19 +1286,20 @@ struct sbuiltin_s "!!permu UPPER\n" "!!permu SKELETAL\n" "#ifdef VERTEX_SHADER\n" + "#include \"sys/skeletal.h\"\n" "attribute vec2 v_texcoord;\n" "varying vec2 tc;\n" - "attribute vec3 v_normal;\n" "uniform vec3 e_light_dir;\n" "uniform vec3 e_light_mul;\n" "uniform vec3 e_light_ambient;\n" "varying vec3 light;\n" - "void main (void)\n" + "void main ()\n" "{\n" - " gl_Position = ftetransform();\n" - " light = e_light_ambient + (dot(v_normal,e_light_dir)*e_light_mul);\n" + " vec3 n;\n" + " gl_Position = skeletaltransform_n(n);\n" + " light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul);\n" " tc = v_texcoord;\n" "}\n" "#endif\n" @@ -1215,7 +1321,7 @@ struct sbuiltin_s "varying lowp vec3 light;\n" "uniform lowp vec4 e_colourident;\n" - "void main (void)\n" + "void main ()\n" "{\n" " lowp vec4 col;\n" " col = texture2D(s_t0, tc);\n" @@ -1236,25 +1342,25 @@ struct sbuiltin_s "}\n" "#endif\n" }, - {QR_OPENGL, 120, "defaultskin", + {QR_OPENGL, 110, "defaultskin", "!!permu FULLBRIGHT\n" "!!permu LOWER\n" "!!permu UPPER\n" "!!permu SKELETAL\n" + "varying vec2 tc;\n" + "varying vec3 light;\n" "#ifdef VERTEX_SHADER\n" + "#include \"sys/skeletal.h\"\n" "attribute vec2 v_texcoord;\n" - "varying vec2 tc;\n" - "attribute vec3 v_normal;\n" "uniform vec3 e_light_dir;\n" "uniform vec3 e_light_mul;\n" "uniform vec3 e_light_ambient;\n" - "varying vec3 light;\n" - "#ifndef SKELETAL\nattribute vec4 v_weight;\n#endif\n" - "void main (void)\n" + "void main ()\n" "{\n" - " gl_Position = ftetransform();\n" - " light = e_light_ambient + (dot(v_normal,e_light_dir)*e_light_mul);\n" + " vec3 n;\n" + " gl_Position = skeletaltransform_n(n);\n" + " light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul);\n" " tc = v_texcoord;\n" "}\n" "#endif\n" @@ -1272,11 +1378,9 @@ struct sbuiltin_s "#ifdef FULLBRIGHT\n" "uniform sampler2D s_t3;\n" /*tex_fullbright*/ "#endif\n" - "varying vec2 tc;\n" - "varying vec3 light;\n" "uniform vec4 e_colourident;\n" - "void main (void)\n" + "void main ()\n" "{\n" " vec4 col, sp;\n" " col = texture2D(s_t0, tc);\n" @@ -1299,34 +1403,31 @@ struct sbuiltin_s }, {QR_OPENGL, 110, "lpp_depthnorm", "!!permu BUMP\n" + "!!permu SKELETAL\n" "varying vec2 pos;\n" "varying vec3 norm, tang, bitang;\n" "#if defined(BUMP)\n" "varying vec2 tc;\n" "#endif\n" "#ifdef VERTEX_SHADER\n" + "#include \"sys/skeletal.h\"\n" "attribute vec2 v_texcoord;\n" - "attribute vec3 v_normal;\n" - "attribute vec3 v_svector;\n" - "attribute vec3 v_tvector;\n" - "uniform mat4 m_modelviewprojection;\n" - "void main(void)\n" + "void main()\n" "{\n" - "gl_Position = ftetransform();\n" - "pos = gl_Position.zw;\n" - "norm = v_normal;\n" "#if defined(BUMP)\n" - "tang = v_svector;\n" - "bitang = v_tvector;\n" + "gl_Position = skeletaltransform_nst(norm, tang, bitang);\n" "tc = v_texcoord;\n" + "#else\n" + "gl_Position = skeletaltransform_n(norm);\n" "#endif\n" + "pos = gl_Position.zw;\n" "}\n" "#endif\n" "#ifdef FRAGMENT_SHADER\n" "#if defined(BUMP)\n" "uniform sampler2D s_t0;\n" "#endif\n" - "void main(void)\n" + "void main()\n" "{\n" "vec3 onorm;\n" "#if defined(BUMP)\n" @@ -1343,9 +1444,9 @@ struct sbuiltin_s {QR_OPENGL, 110, "lpp_light", "varying vec4 tf;\n" "#ifdef VERTEX_SHADER\n" - "void main(void)\n" + "void main()\n" "{\n" - "gl_Position = tf = ftetransform();\n" + "tf = ftetransform(); gl_Position = tf;\n" "}\n" "#endif\n" "#ifdef FRAGMENT_SHADER\n" @@ -1368,7 +1469,7 @@ struct sbuiltin_s "return pos.xyz / pos.w;\n" "}\n" - "void main (void)\n" + "void main ()\n" "{\n" "vec3 lightColour = l_lightcolour.rgb;\n" "float lightIntensity = 1.0;\n" @@ -1412,7 +1513,7 @@ struct sbuiltin_s "attribute vec2 v_texcoord;\n" "attribute vec2 v_lmcoord;\n" - "void main (void)\n" + "void main ()\n" "{\n" "tc = v_texcoord;\n" "lm = v_lmcoord;\n" @@ -1429,7 +1530,7 @@ struct sbuiltin_s //"uniform sampler2D s_t5;\n" /*tex_fullbright*/ "uniform float cvar_gl_overbright;\n" - "void main (void)\n" + "void main ()\n" "{\n" "float lmscale = exp2(floor(clamp(cvar_gl_overbright, 0.0, 2.0)));\n" //"gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * vec4(scale, scale, scale, 1.0);\n" @@ -1741,6 +1842,8 @@ struct shader_field_names_s shader_field_names[] = {"l_lightradius", SP_LIGHTRADIUS}, {"l_lightcolour", SP_LIGHTCOLOUR}, {"l_lightposition", SP_LIGHTPOSITION}, + + {"e_rendertexturescale", SP_RENDERTEXTURESCALE}, {NULL} }; @@ -2118,8 +2221,11 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p } } } - if (!foundone && !silent) - Con_Printf("shader %s: param \"%s\" not found\n", shader->name, token); + if (!foundone) + { + if (!silent) + Con_Printf("shader %s: param \"%s\" not found\n", shader->name, token); + } else prog->numparams++; @@ -2240,6 +2346,11 @@ static qboolean ShaderPass_MapGen (shader_t *shader, shaderpass_t *pass, char *t pass->texgen = T_GEN_SOURCECOLOUR; pass->tcgen = TC_GEN_BASE; //FIXME: moo! } + else if (!Q_stricmp (tname, "$sourcecube")) + { + pass->texgen = T_GEN_SOURCECUBE; + pass->tcgen = TC_GEN_BASE; //FIXME: moo! + } else if (!Q_stricmp (tname, "$sourcedepth")) { pass->texgen = T_GEN_SOURCEDEPTH; @@ -2383,13 +2494,13 @@ static void Shaderpass_RGBGen (shader_t *shader, shaderpass_t *pass, char **ptr) else if (!Q_stricmp (token, "oneMinusEntity")) pass->rgbgen = RGB_GEN_ONE_MINUS_ENTITY; else if (!Q_stricmp (token, "vertex")) - pass->rgbgen = RGB_GEN_VERTEX; + pass->rgbgen = RGB_GEN_VERTEX_LIGHTING; else if (!Q_stricmp (token, "oneMinusVertex")) pass->rgbgen = RGB_GEN_ONE_MINUS_VERTEX; else if (!Q_stricmp (token, "lightingDiffuse")) pass->rgbgen = RGB_GEN_LIGHTING_DIFFUSE; else if (!Q_stricmp (token, "exactvertex")) - pass->rgbgen = RGB_GEN_EXACT_VERTEX; + pass->rgbgen = RGB_GEN_VERTEX_EXACT; else if (!Q_stricmp (token, "const") || !Q_stricmp (token, "constant")) { pass->rgbgen = RGB_GEN_CONST; @@ -2606,6 +2717,17 @@ static void Shaderpass_DepthWrite (shader_t *shader, shaderpass_t *pass, char ** pass->shaderbits |= SBITS_MISC_DEPTHWRITE; } +static void Shaderpass_NoDepthTest (shader_t *shader, shaderpass_t *pass, char **ptr) +{ + shader->flags |= SHADER_DEPTHWRITE; + pass->shaderbits |= SBITS_MISC_NODEPTHTEST; +} + +static void Shaderpass_NoDepth (shader_t *shader, shaderpass_t *pass, char **ptr) +{ + shader->flags |= SHADER_DEPTHWRITE; +} + static void Shaderpass_TcMod (shader_t *shader, shaderpass_t *pass, char **ptr) { int i; @@ -2857,6 +2979,8 @@ static shaderkey_t shaderpasskeys[] = {"blendfunc", Shaderpass_BlendFunc }, {"depthfunc", Shaderpass_DepthFunc }, {"depthwrite", Shaderpass_DepthWrite }, + {"nodepthtest", Shaderpass_NoDepthTest }, + {"nodepth", Shaderpass_NoDepth }, {"alphafunc", Shaderpass_AlphaFunc }, {"tcmod", Shaderpass_TcMod }, {"map", Shaderpass_Map }, @@ -2941,6 +3065,7 @@ int Shader_InitCallback (const char *name, int size, void *param) qboolean Shader_Init (void) { + int wibuf[16]; shaderbuflen = 0; if (!r_shaders) @@ -2958,6 +3083,12 @@ qboolean Shader_Init (void) shader_rescan_needed = true; Shader_NeedReload(); Shader_DoReload(); + + memset(wibuf, 0xff, sizeof(wibuf)); + if (!qrenderer) + r_whiteimage = r_nulltex; + else + r_whiteimage = R_LoadTexture("$whiteimage", 4, 4, TF_RGBA32, wibuf, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA); return true; } @@ -3146,12 +3277,17 @@ void Shader_SetBlendmode (shaderpass_t *pass) if ((pass->rgbgen == RGB_GEN_IDENTITY) && (pass->alphagen == ALPHA_GEN_IDENTITY)) { pass->blendmode = PBM_REPLACE; + return; + } + else if ((pass->rgbgen == RGB_GEN_IDENTITY_LIGHTING) && (pass->alphagen == ALPHA_GEN_IDENTITY)) + { + pass->shaderbits &= ~SBITS_BLEND_BITS; + pass->shaderbits |= SBITS_SRCBLEND_ONE; + pass->shaderbits |= SBITS_DSTBLEND_ZERO; + pass->blendmode = PBM_REPLACELIGHT; } else { -#ifdef _MSC_VER -#pragma message("is this correct?") -#endif pass->shaderbits &= ~SBITS_BLEND_BITS; pass->shaderbits |= SBITS_SRCBLEND_ONE; pass->shaderbits |= SBITS_DSTBLEND_ZERO; @@ -3254,7 +3390,8 @@ void Shader_Readpass (shader_t *shader, char **ptr) // check some things if ( ignore ) { - Shader_Free ( shader ); + Shader_FreePass (pass); + shader->numpasses--; return; } @@ -3293,8 +3430,8 @@ void Shader_Readpass (shader_t *shader, char **ptr) if ((shader->flags & SHADER_SKY) && (shader->flags & SHADER_DEPTHWRITE)) { -#ifdef _MSC_VER -#pragma message("is this valid?") +#ifdef warningmsg +#pragma warningmsg("is this valid?") #endif pass->shaderbits &= ~SBITS_MISC_DEPTHWRITE; } @@ -3434,9 +3571,9 @@ void Shader_SetFeatures ( shader_t *s ) case RGB_GEN_LIGHTING_DIFFUSE: s->features |= MF_NORMALS; break; - case RGB_GEN_VERTEX: + case RGB_GEN_VERTEX_LIGHTING: case RGB_GEN_ONE_MINUS_VERTEX: - case RGB_GEN_EXACT_VERTEX: + case RGB_GEN_VERTEX_EXACT: s->features |= MF_COLORS; break; default: @@ -3488,7 +3625,7 @@ void Shader_Finish (shader_t *s) /*or if its purely a skybox and has missing textures*/ if (!s->numpasses) for (i = 0; i < 6; i++) - if (missing_texture.num == s->skydome->farbox_textures[i].num) + if (missing_texture.ref == s->skydome->farbox_textures[i].ref) s->flags = 0; if (!(s->flags & SHADER_SKY)) { @@ -3521,7 +3658,7 @@ void Shader_Finish (shader_t *s) else { pass->texgen = T_GEN_SINGLEMAP; - pass->anim_frames[0] = R_LoadHiResTexture(s->name, NULL, IF_NOALPHA); + TEXASSIGN(pass->anim_frames[0], R_LoadHiResTexture(s->name, NULL, IF_NOALPHA)); if (!TEXVALID(pass->anim_frames[0])) { Con_Printf("Shader %s failed to load default texture\n", s->name); @@ -3530,7 +3667,7 @@ void Shader_Finish (shader_t *s) Con_Printf("Shader %s with no passes and no surfaceparm nodraw, inserting pass\n", s->name); } pass->shaderbits |= SBITS_MISC_DEPTHWRITE; - pass->rgbgen = RGB_GEN_VERTEX; + pass->rgbgen = RGB_GEN_VERTEX_LIGHTING; pass->alphagen = ALPHA_GEN_IDENTITY; pass->numMergedPasses = 1; Shader_SetBlendmode(pass); @@ -3576,7 +3713,7 @@ void Shader_Finish (shader_t *s) pass = s->passes; for (i = 0; i < s->numpasses; i++, pass++) { - if (pass->rgbgen == RGB_GEN_VERTEX) + if (pass->rgbgen == RGB_GEN_VERTEX_LIGHTING) break; } @@ -3628,7 +3765,7 @@ void Shader_Finish (shader_t *s) memcpy ( &s->passes[0], pass, sizeof(shaderpass_t) ); } - s->passes[0].rgbgen = RGB_GEN_VERTEX; + s->passes[0].rgbgen = RGB_GEN_VERTEX_LIGHTING; s->passes[0].alphagen = ALPHA_GEN_IDENTITY; s->passes[0].blendmode = 0; s->passes[0].flags &= ~(SHADER_PASS_ANIMMAP|SHADER_PASS_NOCOLORARRAY); @@ -3666,7 +3803,9 @@ done:; if (pass->rgbgen == RGB_GEN_UNKNOWN) { - if (!s->fog_dist && !(pass->flags & SHADER_PASS_LIGHTMAP)) + if ( (pass->shaderbits & SBITS_SRCBLEND_BITS) == 0 + || (pass->shaderbits & SBITS_SRCBLEND_BITS) == SBITS_SRCBLEND_ONE + || (pass->shaderbits & SBITS_SRCBLEND_BITS) == SBITS_SRCBLEND_SRC_ALPHA) pass->rgbgen = RGB_GEN_IDENTITY_LIGHTING; else pass->rgbgen = RGB_GEN_IDENTITY; @@ -3804,8 +3943,6 @@ void Shader_UpdateRegistration (void) void R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader) { - extern cvar_t gl_bump; - /*dlights/realtime lighting needs some stuff*/ if (!TEXVALID(tn->base)) { @@ -3814,7 +3951,7 @@ void R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader) if (TEXVALID(tn->base)) shader->flags &= ~SHADER_NOIMAGE; - if (gl_bump.ival) + if (r_loadbumpmapping) { if (!TEXVALID(tn->bump)) tn->bump = R_LoadHiResTexture(va("%s_norm", shader->name), NULL, IF_NOALPHA); @@ -3832,7 +3969,12 @@ void R_BuildDefaultTexnums(texnums_t *tn, shader_t *shader) tn->upperoverlay = R_LoadHiResTexture(va("%s_shirt", shader->name), NULL, 0); } - shader->defaulttextures = *tn; + TEXASSIGN(shader->defaulttextures.base, tn->base); + TEXASSIGN(shader->defaulttextures.specular, tn->specular); + TEXASSIGN(shader->defaulttextures.fullbright, tn->fullbright); + TEXASSIGN(shader->defaulttextures.bump, tn->bump); + TEXASSIGN(shader->defaulttextures.loweroverlay, tn->loweroverlay); + TEXASSIGN(shader->defaulttextures.upperoverlay, tn->upperoverlay); } void Shader_DefaultScript(char *shortname, shader_t *s, const void *args) @@ -3936,7 +4078,7 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args) "{\n" "map $diffuse\n" "tcgen base\n" - "if gl_bump\n" + "if $deluxmap\n" "[\n" "blendfunc gl_one gl_zero\n" "]\n" @@ -4268,7 +4410,7 @@ void Shader_DefaultBSPVertex(char *shortname, shader_t *s, const void *args) pass->tcgen = TC_GEN_BASE; pass->anim_frames[0] = R_LoadHiResTexture(shortname, NULL, 0); pass->shaderbits |= SBITS_MISC_DEPTHWRITE; - pass->rgbgen = RGB_GEN_VERTEX; + pass->rgbgen = RGB_GEN_VERTEX_LIGHTING; pass->alphagen = ALPHA_GEN_IDENTITY; pass->numMergedPasses = 1; Shader_SetBlendmode(pass); @@ -4293,7 +4435,7 @@ void Shader_DefaultBSPFlare(char *shortname, shader_t *s, const void *args) pass->flags = SHADER_PASS_NOCOLORARRAY; pass->shaderbits |= SBITS_SRCBLEND_ONE|SBITS_DSTBLEND_ONE; pass->anim_frames[0] = R_LoadHiResTexture(shortname, NULL, 0); - pass->rgbgen = RGB_GEN_VERTEX; + pass->rgbgen = RGB_GEN_VERTEX_LIGHTING; pass->alphagen = ALPHA_GEN_IDENTITY; pass->numtcmods = 0; pass->tcgen = TC_GEN_BASE; @@ -4322,9 +4464,7 @@ void Shader_DefaultSkin(char *shortname, shader_t *s, const void *args) "if $lpp\n" "[\n" "program defaultskin\n" - "]\n" - "else\n" - "[\n" + "][\n" "program lpp_skin\n" "]\n" "{\n" @@ -4382,11 +4522,11 @@ void Shader_Default2D(char *shortname, shader_t *s, const void *genargs) "}\n" ); - s->defaulttextures.base = R_LoadHiResTexture(shortname, NULL, IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP); + TEXASSIGN(s->defaulttextures.base, R_LoadHiResTexture(shortname, NULL, IF_NOPICMIP|IF_NOMIPMAP|IF_CLAMP)); if (!TEXVALID(s->defaulttextures.base)) { unsigned char data[4*4] = {0}; - s->defaulttextures.base = R_LoadTexture8("black", 4, 4, data, 0, 0); + TEXASSIGN(s->defaulttextures.base, R_LoadTexture8("black", 4, 4, data, 0, 0)); s->flags |= SHADER_NOIMAGE; s->width = 64; diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 7cff501dd..59460706d 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -1001,60 +1001,252 @@ static qboolean Sh_LeafInView(qbyte *lightvis, qbyte *vvis) return false; } -static void Sh_Scissor (int x, int y, int width, int height) +typedef struct +{ + int x; + int y; + int width; + int height; + double dmin; + double dmax; +} srect_t; +static void Sh_Scissor (srect_t r) { #if 0 //visible scissors - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho (0, glwidth, glheight, 0, -99999, 99999); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); -// GL_Set2D(); + extern cvar_t temp1; + if (temp1.ival) + { + qglMatrixMode(GL_PROJECTION); + qglPushMatrix(); + qglLoadIdentity(); + qglOrtho (0, vid.pixelwidth, vid.pixelheight, 0, -99999, 99999); + qglMatrixMode(GL_MODELVIEW); + qglPushMatrix(); + qglLoadIdentity(); + // GL_Set2D(); - glColor4f(1,1,1,1); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE ); - glDisable(GL_TEXTURE_2D); - GL_TexEnv(GL_REPLACE); + qglColor4f(1,1,1,1); + qglDisable(GL_DEPTH_TEST); + qglDisable(GL_SCISSOR_TEST); + qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE ); + qglDisable(GL_TEXTURE_2D); - glBegin(GL_LINE_LOOP); - glVertex2f(x, y); - glVertex2f(x+glwidth, y); - glVertex2f(x+glwidth, y+glheight); - glVertex2f(x, y+glheight); - glEnd(); + qglBegin(GL_LINE_LOOP); + qglVertex2f(r.x, vid.pixelheight - (r.y + r.height)); + qglVertex2f(r.x+r.width, vid.pixelheight - (r.y + r.height)); + qglVertex2f(r.x+r.width, vid.pixelheight - (r.y)); + qglVertex2f(r.x, vid.pixelheight - (r.y)); + qglEnd(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); + + qglMatrixMode(GL_PROJECTION); + qglPopMatrix(); + qglMatrixMode(GL_MODELVIEW); + qglPopMatrix(); + } #endif - qglScissor(x, vid.pixelheight - (y + height),width,height); + qglScissor(r.x, r.y, r.width, r.height); + + if (qglDepthBoundsEXT) + { + qglDepthBoundsEXT(r.dmin, r.dmax); + qglEnable(GL_DEPTH_BOUNDS_TEST_EXT); + } } +#if 0 +static qboolean Sh_ScissorForSphere(vec3_t center, float radius, vrect_t *rect) +{ + /*return false to say that its fully offscreen*/ + + float v[4], tempv[4]; + extern cvar_t temp1; + int i; + vrect_t r; + + radius *= temp1.value; + + rect->x = 0; + rect->y = 0; + rect->width = vid.pixelwidth; + rect->height = vid.pixelheight; + + +/* + for (i = 0; i < 4; i++) + { + v[3] = 1; + VectorMA(center, radius, frustum[i].normal, v); + + tempv[0] = r_refdef.m_view[0]*v[0] + r_refdef.m_view[4]*v[1] + r_refdef.m_view[8]*v[2] + r_refdef.m_view[12]*v[3]; + tempv[1] = r_refdef.m_view[1]*v[0] + r_refdef.m_view[5]*v[1] + r_refdef.m_view[9]*v[2] + r_refdef.m_view[13]*v[3]; + tempv[2] = r_refdef.m_view[2]*v[0] + r_refdef.m_view[6]*v[1] + r_refdef.m_view[10]*v[2] + r_refdef.m_view[14]*v[3]; + tempv[3] = r_refdef.m_view[3]*v[0] + r_refdef.m_view[7]*v[1] + r_refdef.m_view[11]*v[2] + r_refdef.m_view[15]*v[3]; + + product[0] = r_refdef.m_projection[0]*tempv[0] + r_refdef.m_projection[4]*tempv[1] + r_refdef.m_projection[8]*tempv[2] + r_refdef.m_projection[12]*tempv[3]; + product[1] = r_refdef.m_projection[1]*tempv[0] + r_refdef.m_projection[5]*tempv[1] + r_refdef.m_projection[9]*tempv[2] + r_refdef.m_projection[13]*tempv[3]; + product[2] = r_refdef.m_projection[2]*tempv[0] + r_refdef.m_projection[6]*tempv[1] + r_refdef.m_projection[10]*tempv[2] + r_refdef.m_projection[14]*tempv[3]; + product[3] = r_refdef.m_projection[3]*tempv[0] + r_refdef.m_projection[7]*tempv[1] + r_refdef.m_projection[11]*tempv[2] + r_refdef.m_projection[15]*tempv[3]; + + v[0] /= v[3]; + v[1] /= v[3]; + v[2] /= v[3]; + + out[0] = (1+v[0])/2; + out[1] = (1+v[1])/2; + out[2] = (1+v[2])/2; + + r.x + } +*/ + return false; +} +#endif + #define BoxesOverlap(a,b,c,d) ((a)[0] <= (d)[0] && (b)[0] >= (c)[0] && (a)[1] <= (d)[1] && (b)[1] >= (c)[1] && (a)[2] <= (d)[2] && (b)[2] >= (c)[2]) -static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) +static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs, srect_t *r) +{ + static const edge[12][2] = + { + {0, 1}, {0, 2}, {1, 3}, {2, 3}, + {4, 5}, {4, 6}, {5, 7}, {6, 7}, + {0, 4}, {1, 5}, {2, 6}, {3, 7} + }; + //the box is a simple cube. + //clip each vert to the near clip plane + //insert a replacement vertex for edges that cross the nearclip plane where it crosses + //calc the scissor rect from projecting the verts that survived, plus the clipped edge ones. + float ncpdist; + float dist[8]; + int sign[8]; + vec4_t vert[20]; + vec3_t p[8]; + int numverts = 0, i, v1, v2; + vec4_t v,tv; + float frac; + float x,x1,x2,y,y1,y2; + double z, z1, z2; + extern cvar_t gl_mindist; + + r->x = 0; + r->y = 0; + r->width = vid.pixelwidth; + r->height = vid.pixelheight; + r->dmin = 0; + r->dmax = 1; + if (0)//!r_shadow_scissor.integer) + { + return false; + } + /*if view is inside the box, then skip this maths*/ +// if (BoxesOverlap(r_refdef.vieworg, r_refdef.vieworg, mins, maxs)) +// { +// return false; +// } + + ncpdist = DotProduct(r_refdef.vieworg, vpn) + gl_mindist.value; + + for (i = 0; i < 8; i++) + { + p[i][0] = (i & 1) ? mins[0] : maxs[0]; + p[i][1] = (i & 2) ? mins[1] : maxs[1]; + p[i][2] = (i & 4) ? mins[2] : maxs[2]; + dist[i] = ncpdist - DotProduct(p[i], vpn); + sign[i] = (dist[i] > 0); + if (!sign[i]) + { + VectorCopy(p[i], vert[numverts]); + numverts++; + } + } + + /*fully clipped by near plane*/ + if (!numverts) + return true; + + if (numverts != 8) + { + /*crosses near clip plane somewhere*/ + for (i = 0; i < 12; i++) + { + v1 = edge[i][0]; + v2 = edge[i][1]; + if (sign[v1] != sign[v2]) + { + frac = dist[v1] / (dist[v1] - dist[v2]); + VectorInterpolate(p[v1], frac, p[v2], vert[numverts]); + numverts++; + } + } + } + x1 = y1 = z1 = 1; + x2 = y2 = z2 = -1; + /*transform each vert to get the screen pos*/ + for (i = 0; i < numverts; i++) + { + vert[i][3] = 1; + Matrix4x4_CM_Transform4(r_refdef.m_view, vert[i], tv); + Matrix4x4_CM_Transform4(r_refdef.m_projection, tv, v); + + x = v[0] / v[3]; + y = v[1] / v[3]; + z = (double)v[2] / v[3]; + if (x < x1) x1 = x; + if (x > x2) x2 = x; + if (y < y1) y1 = y; + if (y > y2) y2 = y; + if (z < z1) z1 = z; + if (z > z2) z2 = z; + } + x1 = ((1+x1) * r_refdef.vrect.width * vid.pixelwidth) / (vid.width * 2); + x2 = ((1+x2) * r_refdef.vrect.width * vid.pixelwidth) / (vid.width * 2); + y1 = ((1+y1) * r_refdef.vrect.height * vid.pixelheight) / (vid.height * 2); + y2 = ((1+y2) * r_refdef.vrect.height * vid.pixelheight) / (vid.height * 2); + z1 = (1+z1) / 2; + z2 = (1+z2) / 2; + + if (x1 < 0) + x1 = 0; + if (y1 < 0) + y1 = 0; + if (x2 < 0) + x2 = 0; + if (y1 > r_refdef.vrect.height * vid.pixelheight / vid.height) + y1 = r_refdef.vrect.height * vid.pixelheight / vid.height; + if (y2 > r_refdef.vrect.height * vid.pixelheight / vid.height) + y2 = r_refdef.vrect.height * vid.pixelheight / vid.height; + r->x = floor(x1); + r->y = floor(y1); + r->width = ceil(x2) - r->x; + r->height = ceil(y2) - r->y; + + r->x += r_refdef.vrect.x; + r->y += r_refdef.vrect.y; + r->dmin = z1; + r->dmax = z2; + return false; +} + +#if 0 +static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs, vrect_t *r) { int i, ix1, iy1, ix2, iy2; float x1, y1, x2, y2, x, y, f; vec3_t smins, smaxs; vec4_t v, v2; - int r_view_x = 0; - int r_view_y = 0; - int r_view_width = vid.pixelwidth; - int r_view_height = vid.pixelheight; + + r->x = 0; + r->y = 0; + r->width = vid.pixelwidth; + r->height = vid.pixelheight; if (0)//!r_shadow_scissor.integer) { - Sh_Scissor(r_view_x, r_view_y, r_view_width, r_view_height); return false; } - // if view is inside the box, just say yes it's visible + // if view is inside the box, just say yes it's fully visible if (BoxesOverlap(r_refdef.vieworg, r_refdef.vieworg, mins, maxs)) { - Sh_Scissor(r_view_x, r_view_y, r_view_width, r_view_height); return false; } for (i = 0;i < 3;i++) @@ -1070,11 +1262,10 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) v2[i] = mins[i]; } } - f = DotProduct(vpn, r_refdef.vieworg) + 1; + f = DotProduct(vpn, r_refdef.vieworg); if (DotProduct(vpn, v2) <= f) { - // entirely behind nearclip plane - Sh_Scissor(r_view_x, r_view_y, r_view_width, r_view_height); + // entirely behind nearclip plane, entirely obscured return true; } if (DotProduct(vpn, v) >= f) @@ -1088,8 +1279,8 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) v[2] = (i & 4) ? mins[2] : maxs[2]; v[3] = 1.0f; Matrix4x4_CM_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); - v2[0]*=r_view_width; - v2[1]*=r_view_height; + v2[0]*=vid.pixelwidth; + v2[1]*=vid.pixelheight; // GL_TransformToScreen(v, v2); //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); x = v2[0]; @@ -1160,8 +1351,8 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) v[2] = v2[0] * vright[2] + v2[1] * vup[2] + v2[2] * vpn[2] + r_refdef.vieworg[2]; v[3] = 1.0f; Matrix4x4_CM_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); - v2[0]*=r_view_width; - v2[1]*=r_view_height; + v2[0]*=vid.pixelwidth; + v2[1]*=vid.pixelheight; //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); x = v2[0]; y = v2[1]; @@ -1189,8 +1380,8 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) v[2] = (i & 4) ? mins[2] : maxs[2]; v[3] = 1.0f; Matrix4x4_CM_Project(v, v2, r_refdef.viewangles, r_refdef.vieworg, r_refdef.fov_x, r_refdef.fov_y); - v2[0]*=r_view_width; - v2[1]*=r_view_height; + v2[0]*=vid.pixelwidth; + v2[1]*=vid.pixelheight; //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]); if (v2[2] > 0) { @@ -1210,17 +1401,21 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) ix2 = x2 + 1.0f; iy2 = y2 + 1.0f; //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2); - if (ix1 < r_view_x) ix1 = r_view_x; - if (iy1 < r_view_y) iy1 = r_view_y; - if (ix2 > r_view_x + r_view_width) ix2 = r_view_x + r_view_width; - if (iy2 > r_view_y + r_view_height) iy2 = r_view_y + r_view_height; + if (ix1 < r->x) ix1 = r->x; + if (iy1 < r->y) iy1 = r->y; + if (ix2 > r->x + r->width) ix2 = r->x + r->width; + if (iy2 > r->y + r->height) iy2 = r->y + r->height; if (ix2 <= ix1 || iy2 <= iy1) return true; // set up the scissor rectangle - qglScissor(ix1, iy1, ix2 - ix1, iy2 - iy1); -// qglEnable(GL_SCISSOR_TEST); + + r->x = ix1; + r->y = iy1; + r->width = ix2 - ix1; + r->height = iy2 - iy1; return false; } +#endif void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture) @@ -1376,7 +1571,7 @@ void Sh_GenShadowMap (dlight_t *l, qbyte *lvis) if (!TEXVALID(l->stexture)) { - l->stexture = GL_AllocNewTexture(smsize, smsize); + l->stexture = GL_AllocNewTexture("***shadowmap***", smsize, smsize); GL_MTBind(0, GL_TEXTURE_2D, l->stexture); qglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32_ARB, smsize, smsize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); @@ -1453,6 +1648,7 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis) vec3_t mins, maxs; qbyte *lvis; qbyte lvisb[MAX_MAP_LEAFS/8]; + srect_t rect; if (R_CullSphere(l->origin, l->radius)) { @@ -1468,7 +1664,7 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis) maxs[1] = l->origin[1] + l->radius; maxs[2] = l->origin[2] + l->radius; - if (Sh_ScissorForBox(mins, maxs)) + if (Sh_ScissorForBox(mins, maxs, &rect)) { bench.numscissorculled++; return; @@ -1528,6 +1724,9 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis) bench.numlights++; + Sh_Scissor(rect); + qglEnable(GL_STENCIL_TEST); + qglMatrixMode(GL_TEXTURE); GL_MTBind(7, GL_TEXTURE_2D, l->stexture); @@ -1542,7 +1741,7 @@ static void Sh_DrawShadowMapLight(dlight_t *l, vec3_t colour, qbyte *vvis) ve = 0; - BE_SelectDLight(l, colour); + GLBE_SelectDLight(l, colour); BE_SelectMode(l->fov?BEM_SMAPLIGHTSPOT:BEM_SMAPLIGHT); Sh_DrawEntLighting(l, colour); @@ -1618,8 +1817,8 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour) #define PROJECTION_DISTANCE (float)(dl->radius*2)//0x7fffffff /*Fixme: this is brute forced*/ -#ifdef _MSC_VER -#pragma message("brush shadows are bruteforced") +#ifdef warningmsg +#pragma warningmsg("brush shadows are bruteforced") #endif static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e) { @@ -1801,6 +2000,7 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) int sincrw; int leaf; qbyte *lvis; + srect_t rect; qbyte lvisb[MAX_MAP_LEAFS/8]; @@ -1844,19 +2044,20 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) } //sets up the gl scissor (and culls to view) - if (Sh_ScissorForBox(mins, maxs)) + if (Sh_ScissorForBox(mins, maxs, &rect)) { bench.numscissorculled++; return false; //this doesn't cull often. } bench.numlights++; - BE_SelectDLight(dl, colour); + GLBE_SelectDLight(dl, colour); BE_SelectMode(BEM_STENCIL); //The backend doesn't maintain scissor state. - //qglEnable(GL_SCISSOR_TEST); //The backend doesn't maintain stencil test state either - it needs to be active for more than just stencils, or disabled. its awkward. + Sh_Scissor(rect); + qglEnable(GL_SCISSOR_TEST); qglEnable(GL_STENCIL_TEST); //FIXME: is it practical to test to see if scissors allow not clearing the stencil buffer? @@ -1998,6 +2199,7 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis) { vec3_t mins, maxs; + srect_t rect; if (R_CullSphere(dl->origin, dl->radius)) { @@ -2041,16 +2243,19 @@ static void Sh_DrawShadowlessLight(dlight_t *dl, vec3_t colour, qbyte *vvis) maxs[2] = dl->origin[2] + dl->radius; -//sets up the gl scissor (and culls to view) - if (Sh_ScissorForBox(mins, maxs)) +//sets up the gl scissor (actually just culls to view) + if (Sh_ScissorForBox(mins, maxs, &rect)) { bench.numscissorculled++; return; //was culled. } + qglDisable(GL_SCISSOR_TEST); + if (qglDepthBoundsEXT) + qglDisable(GL_DEPTH_BOUNDS_TEST_EXT); bench.numlights++; - BE_SelectDLight(dl, colour); + GLBE_SelectDLight(dl, colour); BE_SelectMode(BEM_LIGHT); Sh_DrawEntLighting(dl, colour); } @@ -2142,6 +2347,8 @@ void Sh_DrawLights(qbyte *vis) } qglDisable(GL_SCISSOR_TEST); + if (qglDepthBoundsEXT) + qglDisable(GL_DEPTH_BOUNDS_TEST_EXT); BE_SelectMode(BEM_STANDARD); // if (developer.value) diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index b618ab1f8..333b3c0d6 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -191,12 +191,11 @@ FTEPFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT; //quick hack that made quake work on both 1 and 1.1 gl implementations. BINDTEXFUNCPTR bindTexFunc; +#define GLchar char #if defined(_DEBUG) && !defined(DEBUG) #define DEBUG #endif #if defined(DEBUG) - -#define GLchar char typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id, GLenum category, GLenum severity, @@ -279,7 +278,6 @@ void (APIENTRY myGLDEBUGPROCAMD)(GLuint id, int gl_mtexarbable=0; //max texture units qboolean gl_mtexable = false; -int gl_bumpmappingpossible; qboolean gammaworks; //if the gl drivers can set proper gamma. @@ -318,18 +316,6 @@ qboolean GL_CheckExtension(char *extname) return !!strstr(gl_extensions, extname); } -texid_t GL_AllocNewTexture(int w, int h) -{ - texid_t r; - qglGenTextures(1, &r.num); - return r; -} - -void GL_DestroyTexture(texid_t tex) -{ - qglDeleteTextures(1, &tex.num); -} - void APIENTRY GL_DrawRangeElementsEmul(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) { qglDrawElements(mode, count, type, indices); @@ -346,8 +332,6 @@ void APIENTRY GL_ClientStateStub(GLenum array) #define getglext(name) getglfunction(name) void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) { - extern cvar_t gl_bump; - memset(&gl_config, 0, sizeof(gl_config)); gl_config.glversion = ver; @@ -397,9 +381,6 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) mtexid0 = 0; mtexid1 = 0; - //none of them bumpmapping possibilities. - gl_bumpmappingpossible = false; - //no GL_ATI_separate_stencil qglStencilOpSeparateATI = NULL; @@ -528,6 +509,13 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) gl_config.arb_texture_compression = true; } + if (GL_CheckExtension("GL_EXT_depth_bounds_test")) + qglDepthBoundsEXT = (void *)getglext("glDepthBoundsEXT"); + else if (GL_CheckExtension("GL_NV_depth_bounds_test")) + qglDepthBoundsEXT = (void *)getglext("glDepthBoundsNV"); + else + qglDepthBoundsEXT = NULL; + if (GL_CheckExtension("GL_ATI_pn_triangles")) { qglPNTrianglesfATI = (void *)getglext("glPNTrianglesfATI"); @@ -556,9 +544,6 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) gl_config.arb_texture_cube_map = GL_CheckExtension("GL_ARB_texture_cube_map"); - if (gl_mtexarbable && gl_config.arb_texture_cube_map && gl_config.arb_texture_env_combine && gl_config.arb_texture_env_dot3 && !COM_CheckParm("-nobump") && gl_bump.value) - gl_bumpmappingpossible = true; - /*vbos*/ if (GL_CheckExtension("GL_ARB_vertex_buffer_object")) { @@ -574,7 +559,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) // glslang //the gf2 to gf4 cards emulate vertex_shader and thus supports shader_objects. //but our code kinda requires both for clean workings. - if (gl_config.glversion >= 2) + if (gl_config.glversion >= 2)// && (gl_config.gles || 0)) { /*core names are different from extension names (more functions too)*/ gl_config.arb_shader_objects = true; @@ -680,87 +665,237 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) #endif } +static const char *glsl_hdrs[] = +{ + "sys/skeletal.h", + "attribute vec3 v_normal;\n" + "attribute vec3 v_svector;\n" + "attribute vec3 v_tvector;\n" + "#ifdef SKELETAL\n" + "attribute vec4 v_bone;" + "attribute vec4 v_weight;" + "uniform mat3x4 m_bones["STRINGIFY(MAX_BONES)"];\n" + + "vec4 skeletaltransform()" + "{" + "mat3x4 wmat;\n" + "wmat = m_bones[int(v_bone.x)] * v_weight.x;\n" + "wmat += m_bones[int(v_bone.y)] * v_weight.y;\n" + "wmat += m_bones[int(v_bone.z)] * v_weight.z;\n" + "wmat += m_bones[int(v_bone.w)] * v_weight.w;\n" + "return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);" + "}\n" + "vec4 skeletaltransform_nst(out vec3 n, out vec3 t, out vec3 b)" + "{" + "mat3x4 wmat;\n" + "wmat = m_bones[int(v_bone.x)] * v_weight.x;" + "wmat += m_bones[int(v_bone.y)] * v_weight.y;" + "wmat += m_bones[int(v_bone.z)] * v_weight.z;" + "wmat += m_bones[int(v_bone.w)] * v_weight.w;" + "n = vec4(v_normal.xyz, 1.0) * wmat;" + "t = vec4(v_svector.xyz, 1.0) * wmat;" + "b = vec4(v_tvector.xyz, 1.0) * wmat;" + "return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);" + "}\n" + "vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)" + "{" + "mat3x4 wmat;\n" + "wmat = m_bones[int(v_bone.x)] * v_weight.x;" + "wmat += m_bones[int(v_bone.y)] * v_weight.y;" + "wmat += m_bones[int(v_bone.z)] * v_weight.z;" + "wmat += m_bones[int(v_bone.w)] * v_weight.w;" + "n = vec4(v_normal.xyz, 1.0) * wmat;" + "t = vec4(v_svector.xyz, 1.0) * wmat;" + "b = vec4(v_tvector.xyz, 1.0) * wmat;" + "w = vec4(v_position.xyz, 1.0) * wmat;" + "return m_modelviewprojection * vec4(w, 1.0);" + "}\n" + "vec4 skeletaltransform_n(out vec3 n)" + "{" + "mat3x4 wmat;\n" + "wmat = m_bones[int(v_bone.x)] * v_weight.x;" + "wmat += m_bones[int(v_bone.y)] * v_weight.y;" + "wmat += m_bones[int(v_bone.z)] * v_weight.z;" + "wmat += m_bones[int(v_bone.w)] * v_weight.w;" + "n = vec4(v_normal.xyz, 1.0) * wmat;" + "return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);" + "}\n" + "#else\n" + "#define skeletaltransform() ftetransform()\n" + "vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)" + "{" + "n = v_normal;" + "t = v_svector;" + "b = v_tvector;" + "w = v_position.xyz;" + "return ftetransform();" + "}\n" + "vec4 skeletaltransform_nst(out vec3 n, out vec3 t, out vec3 b)" + "{" + "n = v_normal;" + "t = v_svector;" + "b = v_tvector;" + "return ftetransform();" + "}\n" + "vec4 skeletaltransform_n(out vec3 n)" + "{" + "n = v_normal;" + "return ftetransform();" + "}\n" + "#endif\n" + , + NULL +}; + +qboolean GLSlang_GenerateIncludes(int maxstrings, int *strings, const GLchar *prstrings[], GLint length[], const char *shadersource) +{ + int i; + char *incline, *inc; + char incname[256]; + while((incline=strstr(shadersource, "#include"))) + { + if (*strings == maxstrings) + return false; + + /*emit up to the include*/ + prstrings[*strings] = shadersource; + length[*strings] = incline - shadersource; + *strings += 1; + + incline += 8; + incline = COM_ParseOut (incline, incname, sizeof(incname)); + + for (i = 0; glsl_hdrs[i]; i += 2) + { + if (!strcmp(incname, glsl_hdrs[i])) + { + if (!GLSlang_GenerateIncludes(maxstrings, strings, prstrings, length, glsl_hdrs[i+1])) + return false; + break; + } + } + if (!glsl_hdrs[i]) + { + if (FS_LoadFile(incname, &inc) >= 0) + { + if (!GLSlang_GenerateIncludes(maxstrings, strings, prstrings, length, inc)) + { + FS_FreeFile(inc); + return false; + } + FS_FreeFile(inc); + } + } + + /*move the pointer past the include*/ + shadersource = incline; + } + if (*shadersource) + { + if (*strings == maxstrings) + return false; + + /*dump the remaining shader string*/ + prstrings[*strings] = shadersource; + length[*strings] = strlen(prstrings[*strings]); + *strings += 1; + } + return true; +} + // glslang helper api function definitions // type should be GL_FRAGMENT_SHADER_ARB or GL_VERTEX_SHADER_ARB -GLhandleARB GLSlang_CreateShader (char *name, char *versionline, char **precompilerconstants, char *shadersource, GLenum shadertype) +GLhandleARB GLSlang_CreateShader (char *name, int ver, char **precompilerconstants, const char *shadersource, GLenum shadertype) { GLhandleARB shader; GLint compiled; char str[1024]; int loglen, i; - char *prstrings[6+16]; + const GLchar *prstrings[64+16]; + GLint length[sizeof(prstrings)/sizeof(prstrings[0])]; int strings = 0; - if (versionline) - prstrings[strings++] = versionline; + if (ver) + { + prstrings[strings] = va("#version %u\n", ver); + length[strings] = strlen(prstrings[strings]); + strings++; + } while(*precompilerconstants) - prstrings[strings++] = *precompilerconstants++; + { + prstrings[strings] = *precompilerconstants++; + length[strings] = strlen(prstrings[strings]); + strings++; + } + + prstrings[strings] = "#define ENGINE_"DISTRIBUTION"\n"; + length[strings] = strlen(prstrings[strings]); + strings++; - prstrings[strings++] = "#define ENGINE_"DISTRIBUTION"\n"; switch (shadertype) { case GL_FRAGMENT_SHADER_ARB: - prstrings[strings++] = "#define FRAGMENT_SHADER\n"; + prstrings[strings] = "#define FRAGMENT_SHADER\n"; + length[strings] = strlen(prstrings[strings]); + strings++; if (gl_config.gles) { - prstrings[strings++] = "precision mediump float;\n"; + prstrings[strings] = "precision mediump float;\n"; + length[strings] = strlen(prstrings[strings]); + strings++; } break; case GL_VERTEX_SHADER_ARB: - prstrings[strings++] = "#define VERTEX_SHADER\n"; + prstrings[strings] = "#define VERTEX_SHADER\n"; + length[strings] = strlen(prstrings[strings]); + strings++; if (gl_config.gles) { - prstrings[strings++] = + prstrings[strings] = "#ifdef GL_FRAGMENT_PRECISION_HIGH\n" "precision highp float;\n" "#else\n" "precision mediump float;\n" - "#endif\n"; + "#endif\n" + ; + length[strings] = strlen(prstrings[strings]); + strings++; } if (gl_config.nofixedfunc) { - prstrings[strings++] = + prstrings[strings] = + "attribute vec3 v_position;\n" "#define ftetransform() (m_modelviewprojection * vec4(v_position, 1.0))\n" "uniform mat4 m_modelviewprojection;\n" - "attribute vec3 v_position;\n"; + ; + length[strings] = strlen(prstrings[strings]); + strings++; } else { - prstrings[strings++] = - "#ifdef SKELETAL\n" - "attribute vec4 v_bone;\n" - "attribute vec4 v_weight;\n" - "uniform mat4 m_modelviewprojection;\n" - "uniform mat3x4 m_bones["STRINGIFY(MAX_BONES)"];\n" - "attribute vec3 v_position;\n" - - "vec4 skeletaltransform()\n" - "{" - " mat3x4 wmat;\n" - " wmat = m_bones[int(v_bone.x)] * v_weight.x;\n" - " wmat += m_bones[int(v_bone.y)] * v_weight.y;\n" - " wmat += m_bones[int(v_bone.z)] * v_weight.z;\n" - " wmat += m_bones[int(v_bone.w)] * v_weight.w;\n" - " return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);\n" - "}\n" - "#define ftetransform() skeletaltransform()\n" - "#else\n" - "#define ftetransform() ftransform()\n" - "#define v_position gl_Vertex\n" - "#endif\n"; + prstrings[strings] = + "#define ftetransform ftransform\n" + "#define v_position gl_Vertex\n" + "uniform mat4 m_modelviewprojection;\n" + ; + length[strings] = strlen(prstrings[strings]); + strings++; } break; default: - prstrings[strings++] = "#define UNKNOWN_SHADER\n"; + prstrings[strings] = "#define UNKNOWN_SHADER\n"; + length[strings] = strlen(prstrings[strings]); + strings++; break; } - prstrings[strings++] = shadersource; + + GLSlang_GenerateIncludes(sizeof(prstrings)/sizeof(prstrings[0]), &strings, prstrings, length, shadersource); shader = qglCreateShaderObjectARB(shadertype); - qglShaderSourceARB(shader, strings, (const GLcharARB**)prstrings, NULL); + qglShaderSourceARB(shader, strings, prstrings, length); qglCompileShaderARB(shader); qglGetShaderParameteriv_(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); @@ -771,19 +906,28 @@ GLhandleARB GLSlang_CreateShader (char *name, char *versionline, char **precompi switch (shadertype) { case GL_FRAGMENT_SHADER_ARB: - Con_Printf("Fragment shader compilation error:\n----------\n%s\n----------\n", str); + Con_Printf("Fragment shader (%s) compilation error:\n----------\n%s----------\n", name, str); break; case GL_VERTEX_SHADER_ARB: - Con_Printf("Vertex shader compilation error:\n----------\n%s\n----------\n", str); + Con_Printf("Vertex shader (%s) compilation error:\n----------\n%s----------\n", name, str); break; default: Con_Printf("Shader_CreateShader: This shouldn't happen ever\n"); break; } - Con_Printf("Shader \"%s\" source:\n", name); + Con_DPrintf("Shader \"%s\" source:\n", name); for (i = 0; i < strings; i++) - Con_Printf("%s", prstrings[i]); - Con_Printf("%s\n", str); + { + int j; + if (length[i] < 0) + Con_DPrintf("%s", prstrings[i]); + else + { + for (j = 0; j < length[i]; j++) + Con_DPrintf("%c", prstrings[i][j]); + } + } + Con_DPrintf("%s\n", str); return 0; } @@ -840,30 +984,11 @@ GLhandleARB GLSlang_CreateProgramObject (GLhandleARB vert, GLhandleARB frag) return program; } -#if HASHPROGRAMS -struct compiledshaders_s -{ - int uses; - char *consts; - char *vert; - char *frag; - GLhandleARB handle; - bucket_t buck; -}; - -bucket_t *compiledshadersbuckets[64]; -static hashtable_t compiledshaderstable; -#endif - -GLhandleARB GLSlang_CreateProgram(char *name, char *versionline, char **precompilerconstants, char *vert, char *frag) +GLhandleARB GLSlang_CreateProgram(char *name, int ver, char **precompilerconstants, char *vert, char *frag) { GLhandleARB handle; GLhandleARB vs; GLhandleARB fs; -#if HASHPROGRAMS - unsigned int hashkey; - struct compiledshaders_s *cs; -#endif char *nullconstants = NULL; if (!gl_config.arb_shader_objects) @@ -872,25 +997,8 @@ GLhandleARB GLSlang_CreateProgram(char *name, char *versionline, char **precompi if (!precompilerconstants) precompilerconstants = &nullconstants; -#if HASHPROGRAMS - hashkey = Hash_Key(precompilerconstants, ~0) ^ Hash_Key(frag, ~0); - - cs = Hash_GetKey(&compiledshaderstable, hashkey); - while(cs) - { - if (!strcmp(cs->consts, precompilerconstants)) - if (!strcmp(cs->vert, vert)) - if (!strcmp(cs->frag, frag)) - { - cs->uses++; - return cs->handle; - } - cs = Hash_GetNextKey(&compiledshaderstable, hashkey, cs); - } -#endif - - vs = GLSlang_CreateShader(name, versionline, precompilerconstants, vert, GL_VERTEX_SHADER_ARB); - fs = GLSlang_CreateShader(name, versionline, precompilerconstants, frag, GL_FRAGMENT_SHADER_ARB); + vs = GLSlang_CreateShader(name, ver, precompilerconstants, vert, GL_VERTEX_SHADER_ARB); + fs = GLSlang_CreateShader(name, ver, precompilerconstants, frag, GL_FRAGMENT_SHADER_ARB); if (!vs || !fs) handle = 0; @@ -900,19 +1008,6 @@ GLhandleARB GLSlang_CreateProgram(char *name, char *versionline, char **precompi qglDeleteShaderObject_(vs); qglDeleteShaderObject_(fs); -#if HASHPROGRAMS - cs = Z_Malloc(sizeof(*cs) + strlen(precompilerconstants)+1+strlen(vert)+1+strlen(frag)+1); - cs->consts = (char*)(cs + 1); - cs->vert = cs->consts + strlen(precompilerconstants)+1; - cs->frag = cs->vert + strlen(vert)+1; - cs->handle = handle; - cs->uses = 1; - strcpy(cs->consts, precompilerconstants); - strcpy(cs->vert, vert); - strcpy(cs->frag, frag); - Hash_AddKey(&compiledshaderstable, hashkey, cs, &cs->buck); -#endif - return handle; } @@ -1148,10 +1243,6 @@ void GL_Init(void *(*getglfunction) (char *name)) qglDebugMessageCallbackAMD(myGLDEBUGPROCAMD, NULL); qglGetError(); /*suck up the invalid operation error for non-debug contexts*/ #endif - -#if HASHPROGRAMS - Hash_InitTable(&compiledshaderstable, sizeof(compiledshadersbuckets)/Hash_BytesForBuckets(1), compiledshadersbuckets); -#endif } unsigned int d_8to24rgbtable[256]; @@ -1171,7 +1262,7 @@ rendererinfo_t openglrendererinfo = { GLDraw_Init, - GLDraw_ReInit, + GLDraw_DeInit, GL_LoadTextureFmt, GL_LoadTexture8Pal24, @@ -1234,6 +1325,7 @@ rendererinfo_t openglrendererinfo = { GLBE_ClearVBO, GLBE_UploadAllLightmaps, GLBE_SelectEntity, + GLBE_SelectDLight, GLBE_LightCullModel, "" diff --git a/engine/gl/gl_vidlinuxglx.c b/engine/gl/gl_vidlinuxglx.c index d2454b78f..6ca7fcd43 100644 --- a/engine/gl/gl_vidlinuxglx.c +++ b/engine/gl/gl_vidlinuxglx.c @@ -1105,15 +1105,25 @@ void IN_MouseMove (float *movements, int pnum) #ifdef VM_UI UI_MousePosition(mousecursor_x, mousecursor_y); #endif - } #ifdef PEXT_CSQC - if (CSQC_MouseMove(mx, my)) - { - mx = 0; - my = 0; - } + if (CSQC_MousePosition(mousecursor_x, mousecursor_y)) + { + mx = 0; + my = 0; + } #endif + } + else + { +#ifdef PEXT_CSQC + if (CSQC_MouseMove(mx, my)) + { + mx = 0; + my = 0; + } +#endif + } if (m_filter.value) { diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index 4abdb6f2c..340f37c73 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -174,8 +174,9 @@ RECT window_rect; HMODULE hInstGL = NULL; HMODULE hInstwgl = NULL; -char reqminidriver[MAX_OSPATH]; -char opengldllname[MAX_OSPATH]; +static qboolean usingminidriver; +static char reqminidriver[MAX_OSPATH]; +static char opengldllname[MAX_OSPATH]; //just GetProcAddress with a safty net. void *getglfunc(char *name) @@ -221,6 +222,9 @@ HDC (WINAPI *qwglGetCurrentDC)(VOID); PROC (WINAPI *qwglGetProcAddress)(LPCSTR); BOOL (WINAPI *qwglMakeCurrent)(HDC, HGLRC); BOOL (WINAPI *qSwapBuffers)(HDC); +int (WINAPI *qChoosePixelFormat)(HDC, CONST PIXELFORMATDESCRIPTOR *); +BOOL (WINAPI *qSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *); +int (WINAPI *qDescribePixelFormat)(HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); BOOL (WINAPI *qwglSwapIntervalEXT) (int); @@ -249,6 +253,7 @@ qboolean GLInitialise (char *renderer) { if (!hInstGL || strcmp(reqminidriver, renderer)) { + usingminidriver = false; if (hInstGL) FreeLibrary(hInstGL); hInstGL=NULL; @@ -265,7 +270,10 @@ qboolean GLInitialise (char *renderer) hInstGL = LoadLibrary(opengldllname); if (hInstGL) + { + usingminidriver = true; Con_DPrintf (" Success\n"); + } else Con_DPrintf (" Failed\n"); } @@ -309,7 +317,21 @@ qboolean GLInitialise (char *renderer) qwglGetCurrentDC = (void *)getwglfunc("wglGetCurrentDC"); qwglGetProcAddress = (void *)getwglfunc("wglGetProcAddress"); qwglMakeCurrent = (void *)getwglfunc("wglMakeCurrent"); - qSwapBuffers = SwapBuffers; + + if (usingminidriver) + { + qSwapBuffers = (void *)getglfunc("wglSwapBuffers"); + qChoosePixelFormat = (void *)getglfunc("wglChoosePixelFormat"); + qSetPixelFormat = (void *)getglfunc("wglSetPixelFormat"); + qDescribePixelFormat = (void *)getglfunc("wglDescribePixelFormat"); + } + else + { + qSwapBuffers = SwapBuffers; + qChoosePixelFormat = ChoosePixelFormat; + qSetPixelFormat = SetPixelFormat; + qDescribePixelFormat = DescribePixelFormat; + } qGetDeviceGammaRamp = (void *)getglfunc("wglGetDeviceGammaRamp3DFX"); qSetDeviceGammaRamp = (void *)getglfunc("wglSetDeviceGammaRamp3DFX"); @@ -320,7 +342,7 @@ qboolean GLInitialise (char *renderer) } /*doesn't consider parent offsets*/ -RECT centerrect(unsigned int parentwidth, unsigned int parentheight, unsigned int cwidth, unsigned int cheight) +RECT centerrect(unsigned int parentleft, unsigned int parenttop, unsigned int parentwidth, unsigned int parentheight, unsigned int cwidth, unsigned int cheight) { RECT r; if (!vid_width.ival) @@ -330,23 +352,23 @@ RECT centerrect(unsigned int parentwidth, unsigned int parentheight, unsigned in if (parentwidth < cwidth) { - r.left = 0; - r.right = parentwidth; + r.left = parentleft; + r.right = r.left+parentwidth; } else { - r.left = (parentwidth - cwidth) / 2; + r.left = parentleft + (parentwidth - cwidth) / 2; r.right = r.left + cwidth; } if (parentheight < cheight) { - r.top = 0; - r.bottom = parentheight; + r.top = parenttop; + r.bottom = r.top + parentheight; } else { - r.top = (parentheight - cheight) / 2; + r.top = parenttop + (parentheight - cheight) / 2; r.bottom = r.top + cheight; } @@ -358,7 +380,7 @@ qboolean VID_SetWindowedMode (rendererstate_t *info) { int i; HDC hdc; - int lastmodestate, wwidth, wheight, pwidth, pheight; + int lastmodestate, wwidth, wheight, pleft, ptop, pwidth, pheight; RECT rect; hdc = GetDC(NULL); @@ -385,6 +407,8 @@ qboolean VID_SetWindowedMode (rendererstate_t *info) WindowStyle = WS_CHILDWINDOW|WS_OVERLAPPED; ExWindowStyle = 0; + pleft = sys_parentleft; + ptop = sys_parenttop; pwidth = sys_parentwidth; pheight = sys_parentheight; } @@ -397,6 +421,8 @@ qboolean VID_SetWindowedMode (rendererstate_t *info) WindowStyle |= WS_SIZEBOX | WS_MAXIMIZEBOX; + pleft = 0; + ptop = 0; pwidth = GetSystemMetrics(SM_CXSCREEN); pheight = GetSystemMetrics(SM_CYSCREEN); @@ -414,7 +440,7 @@ qboolean VID_SetWindowedMode (rendererstate_t *info) wwidth = rect.right - rect.left; wheight = rect.bottom - rect.top; - WindowRect = centerrect(pwidth, pheight, wwidth, wheight); + WindowRect = centerrect(pleft, ptop, pwidth, pheight, wwidth, wheight); // Create the DIB window dibwindow = CreateWindowEx ( @@ -770,7 +796,6 @@ int GLVID_SetMode (rendererstate_t *info, unsigned char *palette) vid.recalc_refdef = 1; - maindc = GetDC(mainwindow); if (vid_desktopgamma.value) { HDC hDC = GetDC(GetDesktopWindow()); @@ -1098,7 +1123,7 @@ void GLVID_Recenter_f(void) if (sys_parentwindow && modestate==MS_WINDOWED) { - WindowRect = centerrect(sys_parentwidth, sys_parentheight, vid_width.value, vid_height.value); + WindowRect = centerrect(sys_parentleft, sys_parenttop, sys_parentwidth, sys_parentheight, vid_width.value, vid_height.value); MoveWindow(mainwindow, WindowRect.left, WindowRect.top, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, FALSE); Cvar_ForceCallback(&vid_conautoscale); @@ -1449,14 +1474,14 @@ BOOL bSetupPixelFormat(HDC hDC) } else { - if ((pixelformat = ChoosePixelFormat(hDC, &pfd))) + if ((pixelformat = qChoosePixelFormat(hDC, &pfd))) { TRACE(("dbg: ChoosePixelFormat 1: worked\n")); - if (SetPixelFormat(hDC, pixelformat, &pfd)) + if (qSetPixelFormat(hDC, pixelformat, &pfd)) { TRACE(("dbg: bSetupPixelFormat: we can use the stencil buffer. woot\n")); - DescribePixelFormat(hDC, pixelformat, sizeof(pfd), &pfd); + qDescribePixelFormat(hDC, pixelformat, sizeof(pfd), &pfd); FixPaletteInDescriptor(hDC, &pfd); gl_canstencil = pfd.cStencilBits; return TRUE; @@ -1467,14 +1492,14 @@ BOOL bSetupPixelFormat(HDC hDC) pfd.cStencilBits = 0; gl_canstencil = false; - if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ) + if ( (pixelformat = qChoosePixelFormat(hDC, &pfd)) == 0 ) { Con_Printf("bSetupPixelFormat: ChoosePixelFormat failed (%i)\n", (int)GetLastError()); return FALSE; } } - if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE) + if (qSetPixelFormat(hDC, pixelformat, &pfd) == FALSE) { Con_Printf("bSetupPixelFormat: SetPixelFormat failed (%i)\n", (int)GetLastError()); return FALSE; @@ -1755,7 +1780,7 @@ LONG WINAPI GLMainWndProc ( if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) { - Sys_Quit (); + Cbuf_AddText("\nquit\n", RESTRICT_LOCAL); } break; @@ -1771,6 +1796,8 @@ LONG WINAPI GLMainWndProc ( // fix the leftover Alt from any Alt-Tab or the like that switched us away ClearAllStates (); + Cvar_ForceCallback(&vid_conautoscale); + break; case WM_DESTROY: diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index 49b38cdb8..b3de75de3 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -783,6 +783,12 @@ void R_InitSky (struct texnums_s *tn, texture_t *mt, qbyte *src) Q_snprintfz(name, sizeof(name), "%s_trans", mt->name); Q_strlwr(name); tn->fullbright = R_LoadReplacementTexture(name, NULL, 0); + if (!TEXVALID(tn->fullbright)) + { + Q_snprintfz(name, sizeof(name), "%s_alpha", mt->name); + Q_strlwr(name); + tn->fullbright = R_LoadReplacementTexture(name, NULL, 0); + } if (!TEXVALID(tn->fullbright)) tn->fullbright = R_LoadTexture32(name, 128, 128, trans, IF_NOGAMMA); } diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 37e7dc0ba..f884067ff 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -90,6 +90,7 @@ void GL_InitFogTexture(void); void GL_BeginRendering (void); void GL_EndRendering (void); +void R_NetgraphInit(void); void GLR_NetGraph (void); void GLR_FrameTimeGraph (int frametime); void GL_FlushSkinCache(void); @@ -188,15 +189,15 @@ void GL_Upload24BGR (char *name, qbyte *data, int width, int height, unsigned in void GL_Upload8_EXT (qbyte *data, int width, int height, qboolean mipmap, qboolean alpha); #endif */ -texid_t GL_LoadTexture (char *identifier, int width, int height, qbyte *data, unsigned int flags, unsigned int transtype); -texid_t GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned char *data, unsigned int flags, float bumpscale); -texid_t GL_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags); -texid_t GL_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags); -texid_t GL_LoadTexture32 (char *identifier, int width, int height, void *data, unsigned int flags); -texid_t GL_LoadCompressed(char *name); -texid_t GL_FindTexture (char *identifier); +texid_tf GL_LoadTexture (char *identifier, int width, int height, qbyte *data, unsigned int flags, unsigned int transtype); +texid_tf GL_LoadTexture8Bump (char *identifier, int width, int height, unsigned char *data, unsigned int flags, float bumpscale); +texid_tf GL_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags); +texid_tf GL_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags); +texid_tf GL_LoadTexture32 (char *identifier, int width, int height, void *data, unsigned int flags); +texid_tf GL_LoadCompressed(char *name); +texid_tf GL_FindTexture (char *identifier); -texid_t GL_LoadTextureFB (char *identifier, int width, int height, qbyte *data, unsigned int flags); +texid_tf GL_LoadTextureFB (char *identifier, int width, int height, qbyte *data, unsigned int flags); void GL_Upload8Pal24 (qbyte *data, qbyte *pal, int width, int height, unsigned int flags); /* typedef struct @@ -240,6 +241,7 @@ extern int r_framecount; extern mplane_t frustum[4]; extern float r_wateralphaval; +extern qboolean r_loadbumpmapping; // // view origin @@ -260,10 +262,7 @@ extern texture_t *r_notexture_mip; extern int d_lightstylevalue[256]; // 8.8 fraction of base light value extern texid_t netgraphtexture; // netgraph texture - -extern int mirrortexturenum; // quake texturenum, not gltexturenum -extern qboolean mirror; -extern mplane_t *mirror_plane; +extern shader_t *netgraphshader; extern const char *gl_vendor; extern const char *gl_renderer; @@ -332,7 +331,7 @@ void FTE_DEPRECATED R_IBrokeTheArrays(void); // gl_draw.c // #ifdef GLQUAKE -texid_t GL_LoadPicTexture (qpic_t *pic); +texid_tf GL_LoadPicTexture (qpic_t *pic); void GL_Set2D (void); #endif @@ -341,7 +340,7 @@ void GL_Set2D (void); // qboolean R_ShouldDraw(entity_t *e); #ifdef GLQUAKE -void R_RotateForEntity (float *modelviewmatrix, const entity_t *e, const model_t *mod); +void R_RotateForEntity (float *modelmatrix, float *modelviewmatrix, const entity_t *e, const model_t *mod); void GL_InitSceneProcessingShaders (void); void GL_SetupSceneProcessingTextures (void); @@ -363,11 +362,11 @@ void R_DrawHLModel(entity_t *curent); // // gl_rlight.c // -void GLR_RenderDlights (void); +void R_RenderDlights (void); void R_GenDlightBatches(batch_t *batches[]); +void R_InitFlashblends(void); #ifdef GLQUAKE void GLR_MarkQ2Lights (dlight_t *light, int bit, mnode_t *node); -void R_InitFlashblends (void); int GLR_LightPoint (vec3_t p); #endif void GLQ3_LightGrid(model_t *mod, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); @@ -786,6 +785,8 @@ extern void (APIENTRY *qglFramebufferTexture2DEXT)(GLenum target, GLenum attachm extern void (APIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId); extern GLenum (APIENTRY *qglCheckFramebufferStatusEXT)(GLenum target); +void (APIENTRY *qglDepthBoundsEXT) (GLclampd zmin, GLclampd zmax); + /* extern qboolean gl_arb_fragment_program; extern PFNGLPROGRAMSTRINGARBPROC qglProgramStringARB; @@ -826,7 +827,7 @@ extern FTEPFNGLUNIFORM1IARBPROC qglUniform1iARB; extern FTEPFNGLUNIFORM1FARBPROC qglUniform1fARB; //glslang helper api -GLhandleARB GLSlang_CreateProgram(char *name, char *versionline, char **precompilerconstants, char *vert, char *frag); +GLhandleARB GLSlang_CreateProgram(char *name, int ver, char **precompilerconstants, char *vert, char *frag); GLint GLSlang_GetUniformLocation (int prog, char *name); void GL_SelectProgram(int program); #define GLSlang_UseProgram(prog) GL_SelectProgram(prog) diff --git a/engine/gl/glsupp.h b/engine/gl/glsupp.h index 3d9dd365c..b268fa197 100644 --- a/engine/gl/glsupp.h +++ b/engine/gl/glsupp.h @@ -263,6 +263,10 @@ typedef void (APIENTRY *PFNGLPNTRIANGLESIATIPROC)(GLenum pname, GLint param); typedef void (APIENTRY *PFNGLPNTRIANGLESFATIPROC)(GLenum pname, GLfloat param); #endif +#ifndef GL_EXT_depth_bounds_test +#define GL_EXT_depth_bounds_test 1 +#define GL_DEPTH_BOUNDS_TEST_EXT 0x8890 +#endif #ifndef GL_EXT_stencil_two_side #define GL_EXT_stencil_two_side 1 diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 21b702d28..86d2d075e 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -156,8 +156,8 @@ typedef struct shaderpass_s { RGB_GEN_WAVE, RGB_GEN_ENTITY, RGB_GEN_ONE_MINUS_ENTITY, - RGB_GEN_VERTEX, - RGB_GEN_EXACT_VERTEX, + RGB_GEN_VERTEX_LIGHTING, + RGB_GEN_VERTEX_EXACT, RGB_GEN_ONE_MINUS_VERTEX, RGB_GEN_IDENTITY_LIGHTING, RGB_GEN_IDENTITY, @@ -223,6 +223,8 @@ typedef struct shaderpass_s { T_GEN_SOURCECOLOUR, //used for render-to-texture targets T_GEN_SOURCEDEPTH, //used for render-to-texture targets + T_GEN_SOURCECUBE, //used for render-to-texture targets + T_GEN_VIDEOMAP, //use the media playback as an image source, updating each frame for which it is visible T_GEN_SKYBOX, //use a skybox instead, otherwise T_GEN_SINGLEMAP } texgen; @@ -464,6 +466,7 @@ void GLBE_UploadAllLightmaps(void); void GLBE_DrawWorld (qbyte *vis); qboolean GLBE_LightCullModel(vec3_t org, model_t *model); void GLBE_SelectEntity(entity_t *ent); +void GLBE_SelectDLight(dlight_t *dl, vec3_t colour); #endif #ifdef D3DQUAKE void D3DBE_Init(void); @@ -478,17 +481,17 @@ void D3DBE_UploadAllLightmaps(void); void D3DBE_DrawWorld (qbyte *vis); qboolean D3DBE_LightCullModel(vec3_t org, model_t *model); void D3DBE_SelectEntity(entity_t *ent); +void D3DBE_SelectDLight(dlight_t *dl, vec3_t colour); void D3DShader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag); int D3DShader_FindUniform(union programhandle_u *h, int type, char *name); void D3DShader_Init(void); +void D3DBE_Reset(qboolean before); #endif //Asks the backend to invoke DrawMeshChain for each surface, and to upload lightmaps as required void BE_DrawNonWorld (void); -void D3DBE_Reset(qboolean before); - //Builds a hardware shader from the software representation void BE_GenerateProgram(shader_t *shader); @@ -503,8 +506,6 @@ void Sh_DrawLights(qbyte *vis); void Sh_Shutdown(void); //Draws the depth of ents in the world near the current light void BE_BaseEntShadowDepth(void); -//Sets the given light+colour to be the current one that everything is to be lit/culled by. -void BE_SelectDLight(dlight_t *dl, vec3_t colour); #endif struct shader_field_names_s diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index 4ba5e65c0..e4b8e4366 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -41,6 +41,38 @@ void PRHunkFree(progfuncs_t *progfuncs, int mark) return; } +/*if we ran out of memory, the vm can allocate a new block, but doing so requires fixing up all sorts of pointers*/ +void PRAddressableRelocate(progfuncs_t *progfuncs, char *oldb, char *newb, int oldlen) +{ + unsigned int i; + edictrun_t *e; + for (i=0 ; iedicttable[i]); + if (e && (char*)e->fields >= oldb && (char*)e->fields < oldb+oldlen) + e->fields = ((char*)e->fields - oldb) + newb; + } + + if (progfuncs->stringtable >= oldb && progfuncs->stringtable < oldb+oldlen) + progfuncs->stringtable = (progfuncs->stringtable - oldb) + newb; + + for (i=0; i < maxprogs; i++) + { + if ((char*)prinst->progstate[i].globals >= oldb && (char*)prinst->progstate[i].globals < oldb+oldlen) + prinst->progstate[i].globals = (float*)(((char*)prinst->progstate[i].globals - oldb) + newb); + if (prinst->progstate[i].strings >= oldb && prinst->progstate[i].strings < oldb+oldlen) + prinst->progstate[i].strings = (prinst->progstate[i].strings - oldb) + newb; + } + + for (i = 0; i < numfields; i++) + { + if (field[i].name >= oldb && field[i].name < oldb+oldlen) + field[i].name = (field[i].name - oldb) + newb; + } + + externs->addressablerelocated(progfuncs, oldb, newb, oldlen); +} + //for 64bit systems. :) //addressable memory is memory available to the vm itself for writing. //once allocated, it cannot be freed for the lifetime of the VM. @@ -48,7 +80,46 @@ void *PRAddressableAlloc(progfuncs_t *progfuncs, int ammount) { ammount = (ammount + 4)&~3; //round up to 4 if (addressableused + ammount > addressablesize) - Sys_Error("Not enough addressable memory for progs VM"); + { + /*only do this if the caller states that it can cope with addressable-block relocations/resizes*/ + if (externs->addressablerelocated) + { +#ifdef _WIN32 + char *newblock; + #if 0//def _DEBUG + int oldtot = addressablesize; + #endif + int newsize = (addressableused + ammount + 4096) & ~(4096-1); + newblock = VirtualAlloc (NULL, addressablesize, MEM_RESERVE, PAGE_NOACCESS); + if (newblock) + { + VirtualAlloc (newblock, addressableused, MEM_COMMIT, PAGE_READWRITE); + memcpy(newblock, addressablehunk, addressableused); + #if 0//def _DEBUG + VirtualAlloc (addressablehunk, oldtot, MEM_RESERVE, PAGE_NOACCESS); + #else + VirtualFree (addressablehunk, 0, MEM_RELEASE); + #endif + PRAddressableRelocate(progfuncs, addressablehunk, newblock, addressableused); + addressablehunk = newblock; + addressablesize = newsize; + } +#else + char *newblock; + addressablesize = (addressableused + ammount + 1024*1024) & ~(1024*1024-1); + newblock = realloc(newblock, addressablesize); + if (newblock) + { + PRAddressableRelocate(progfuncs, addressablehunk, newblock, addressableused); + addressablehunk = newblock; + addressablesize = newsize; + } +#endif + } + + if (addressableused + ammount > addressablesize) + Sys_Error("Not enough addressable memory for progs VM"); + } addressableused += ammount; diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 1f854f058..bd14743a2 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -5,11 +5,6 @@ struct edict_s; #include "progsint.h" //#include "crc.h" -/*int maxedicts; - -evalc_t spawnflagscache; -*/ - #ifdef _WIN32 //this is windows all files are written with this endian standard. we do this to try to get a little more speed. #define NOENDIAN @@ -18,30 +13,8 @@ evalc_t spawnflagscache; vec3_t vec3_origin; -//edictrun_t *sv_edicts; -//int sv_num_edicts; - -//int pr_edict_size; // in bytes -//int pr_max_edict_size; - -//unsigned short pr_crc; - fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs); -pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, int bits); - - - -/* -#define MAX_FIELD_LEN 64 -#define GEFV_CACHESIZE 5 - -typedef struct { - ddef_t *pcache; - char field[MAX_FIELD_LEN]; -} gefv_cache; - -static gefv_cache gefvCache[GEFV_CACHESIZE] = {{NULL, ""}, {NULL, ""}}; -*/ +pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, ddefXX_t *key, char *s, int bits); /* ================= @@ -1052,22 +1025,21 @@ Can parse either fields or globals returns false if error ============= */ -pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, int structtype) +pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, ddefXX_t *key, char *s, int structtype) { int i; char string[128]; fdef_t *def; char *v, *w; - void *d; string_t st; dfunction_t *func; - int type = 0; // warning about beign used without initializing it + int type; switch(structtype) { case PST_DEFAULT: - d = (void *)((int *)base + ((ddef16_t*)key)->ofs); + qcptr += ((ddef16_t*)key)->ofs*sizeof(int); if (pr_types) type = pr_types[((ddef16_t*)key)->type & ~DEF_SAVEGLOBAL].type; @@ -1075,7 +1047,7 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, type = ((ddef16_t*)key)->type & ~DEF_SAVEGLOBAL; break; case PST_FTE32: - d = (void *)((int *)base + ((ddef32_t*)key)->ofs); + qcptr += ((ddef32_t*)key)->ofs*sizeof(int); if (pr_types) type = pr_types[((ddef32_t*)key)->type & ~DEF_SAVEGLOBAL].type; @@ -1084,22 +1056,22 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, break; default: Sys_Error("Bad struct type in ED_ParseEpair"); - d = 0; + return false; } switch (type) { case ev_string: st = PR_StringToProgs(progfuncs, ED_NewString (progfuncs, s, 0)); - *(string_t *)d = st; + *(string_t *)(progfuncs->stringtable + qcptr) = st; break; case ev_float: - *(float *)d = (float)atof (s); + *(float *)(progfuncs->stringtable + qcptr) = (float)atof (s); break; case ev_integer: - *(int *)d = atoi (s); + *(int *)(progfuncs->stringtable + qcptr) = atoi (s); break; case ev_vector: @@ -1112,20 +1084,20 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, v++; if (!*v) { - ((float *)d)[i] = (float)atof (w); + ((float *)(progfuncs->stringtable + qcptr))[i] = (float)atof (w); w = v; } else { *v = 0; - ((float *)d)[i] = (float)atof (w); + ((float *)(progfuncs->stringtable + qcptr))[i] = (float)atof (w); w = v = v+1; } } break; case ev_entity: - *(int *)d = atoi (s); + *(int *)(progfuncs->stringtable + qcptr) = atoi (s); break; case ev_field: @@ -1135,13 +1107,13 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, printf ("Can't find field %s\n", s); return false; } - *(int *)d = def->ofs; + *(int *)(progfuncs->stringtable + qcptr) = def->ofs; break; case ev_function: if (s[1]==':'&&s[2]=='\0') { - *(func_t *)d = 0; + *(func_t *)(progfuncs->stringtable + qcptr) = 0; return true; } func = ED_FindFunction (progfuncs, s, &i, -1); @@ -1150,7 +1122,7 @@ pbool ED_ParseEpair (progfuncs_t *progfuncs, void *base, ddefXX_t *key, char *s, printf ("Can't find function %s\n", s); return false; } - *(func_t *)d = (func - pr_progstate[i].functions) | (i<<24); + *(func_t *)(progfuncs->stringtable + qcptr) = (func - pr_progstate[i].functions) | (i<<24); break; default: @@ -1259,7 +1231,7 @@ char *ED_ParseEdict (progfuncs_t *progfuncs, char *data, edictrun_t *ent) } cont: - if (!ED_ParseEpair (progfuncs, ent->fields, (ddefXX_t*)key, qcc_token, PST_FTE32)) + if (!ED_ParseEpair (progfuncs, (char*)ent->fields - progfuncs->stringtable, (ddefXX_t*)key, qcc_token, PST_FTE32)) { continue; // Sys_Error ("ED_ParseEdict: parse error on entities"); @@ -1905,7 +1877,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) else { file = QCC_COM_Parse(file); - ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d16, qcc_token, PST_DEFAULT); + ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, (ddefXX_t*)d16, qcc_token, PST_DEFAULT); } break; case PST_QTEST: @@ -1918,7 +1890,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) else { file = QCC_COM_Parse(file); - ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d32, qcc_token, PST_FTE32); + ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, (ddefXX_t*)d32, qcc_token, PST_FTE32); } break; default: @@ -2004,7 +1976,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) else { file = QCC_COM_Parse(file); - ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d16, qcc_token, PST_DEFAULT); + ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, (ddefXX_t*)d16, qcc_token, PST_DEFAULT); } break; case PST_QTEST: @@ -2017,7 +1989,7 @@ int LoadEnts(progfuncs_t *progfuncs, char *file, float killonspawnflags) else { file = QCC_COM_Parse(file); - ED_ParseEpair(progfuncs, pr_globals, (ddefXX_t*)d32, qcc_token, PST_FTE32); + ED_ParseEpair(progfuncs, (char*)pr_globals - progfuncs->stringtable, (ddefXX_t*)d32, qcc_token, PST_FTE32); } break; default: @@ -2922,9 +2894,6 @@ retry: break; } } - if (st16[i].op >= OP_RAND0 && st16[i].op <= OP_RANDV2) - if (!st16[i].c) - st16[i].c = OFS_RETURN; } if (hexencalling) { @@ -2932,6 +2901,9 @@ retry: { if (st16[i].op >= OP_CALL1 && st16[i].op <= OP_CALL8) st16[i].op += OP_CALL1H - OP_CALL1; + if (st16[i].op >= OP_RAND0 && st16[i].op <= OP_RANDV2) + if (!st16[i].c) + st16[i].c = OFS_RETURN; } } break; @@ -2954,9 +2926,6 @@ retry: break; } } - if (st16[i].op >= OP_RAND0 && st16[i].op <= OP_RANDV2) - if (!st16[i].c) - st16[i].c = OFS_RETURN; } if (hexencalling) { @@ -2964,6 +2933,9 @@ retry: { if (pr_statements32[i].op >= OP_CALL1 && pr_statements32[i].op <= OP_CALL8) pr_statements32[i].op += OP_CALL1H - OP_CALL1; + if (pr_statements32[i].op >= OP_RAND0 && pr_statements32[i].op <= OP_RANDV2) + if (!pr_statements32[i].c) + pr_statements32[i].c = OFS_RETURN; } } break; @@ -3123,7 +3095,7 @@ retry: d16 = ED_FindGlobal16(progfuncs, s); if (!d16) { - printf("Progs requires \"%s\" the external function \"%s\", but the definition was stripped", filename, s); + printf("Progs requires \"%s\" the external function \"%s\", but the definition was stripped\n", filename, s); PRHunkFree(progfuncs, hmark); pr_progs=NULL; return false; @@ -3131,7 +3103,7 @@ retry: ((int *)glob)[d16->ofs] = PR_FindFunc(progfuncs, s, PR_ANY); if (!((int *)glob)[d16->ofs]) - printf("Warning: Runtime-linked function %s was not found in primary progs (loading %s)", s, filename); + printf("Warning: Runtime-linked function %s could not be found (loading %s)\n", s, filename); /* d2 = ED_FindGlobalOfsFromProgs(progfuncs, s, 0, ev_function); if (!d2) diff --git a/engine/qclib/pr_x86.c b/engine/qclib/pr_x86.c index a93e44573..9f1f1acc2 100644 --- a/engine/qclib/pr_x86.c +++ b/engine/qclib/pr_x86.c @@ -56,6 +56,10 @@ struct jitstate unsigned char *code; unsigned int codesize; unsigned int jitstatements; + + float *glob; + unsigned int cachedglobal; + unsigned int cachereg; }; static void EmitByte(struct jitstate *jit, unsigned char byte) @@ -112,7 +116,11 @@ enum REG_ESP, REG_EBP, REG_ESI, - REG_EDI + REG_EDI, + + /*I'm not going to list S1 here, as that makes things too awkward*/ + REG_S0, + REG_NONE }; #define XOR(sr,dr) EmitByte(0x31);EmitByte(0xc0 | (sr<<3) | dr); #define CLEARREG(reg) XOR(reg,reg) @@ -122,6 +130,117 @@ enum #define STOREI(i, addr) EmitByte(0xc7);EmitByte(0x05); EmitAdr(addr);Emit4Byte(i); #define SETREGI(val,reg) EmitByte(0xbe);Emit4Byte(val); +#define ARGREGS(a,b,c) GCache_Load(jit, op[i].a, a, op[i].b, b, op[i].c, c) +#define RESULTREG(r) GCache_Store(jit, op[i].c, r) + +//for the purposes of the cache, 'temp' offsets are only read when they have been written only within the preceeding control block. +//if they were read at any other time, then we must write them out in full. +//this logic applies only to locals of a function. +//#define USECACHE + +static void GCache_Load(struct jitstate *jit, int ao, int ar, int bo, int br, int co, int cr) +{ +#if USECACHE + if (jit->cachedreg != REG_NONE) + { + /*something is cached, if its one of the input offsets then can chain the instruction*/ + + if (jit->cachedglobal === ao && ar != REG_NONE) + { + if (jit->cachedreg == ar) + ar = REG_NONE; + } + if (jit->cachedglobal === bo && br != REG_NONE) + { + if (jit->cachedreg == br) + br = REG_NONE; + } + if (jit->cachedglobal === co && cr != REG_NONE) + { + if (jit->cachedreg == cr) + cr = REG_NONE; + } + + if (!istemp(ao)) + { + /*purge the old cache*/ + switch(jit->cachedreg) + { + case REG_NONE: + break; + case REG_S0: + //fstps glob[C] + EmitByte(0xd9);EmitByte(0x1d);EmitAdr(jit->glob + jit->cachedglobal); + break; + default: + STOREREG(jit->cachedreg, jit->glob + jit->cachedglobal); + break; + } + jit->cachedglobal = -1; + jit->cachedreg = REG_NONE; + } + +#endif + switch(ar) + { + case REG_NONE: + break; + case REG_S0: + //flds glob[A] + EmitByte(0xd9);EmitByte(0x05);EmitAdr(jit->glob + op[i].a); + break; + default: + LOADREG(jit->glob + ao, ar); + break; + } + + switch(br) + { + case REG_NONE: + break; + case REG_S0: + //flds glob[A] + EmitByte(0xd9);EmitByte(0x05);EmitAdr(jit->glob + op[i].b); + break; + default: + LOADREG(jit->glob + bo, br); + break; + } + + switch(cr) + { + case REG_NONE: + break; + case REG_S0: + //flds glob[A] + EmitByte(0xd9);EmitByte(0x05);EmitAdr(jit->glob + op[i].c); + break; + default: + LOADREG(jit->glob + co, cr); + break; + } +} +static void GCache_Store(struct jitstate *jit, int ofs, int reg) +{ +#if USECACHE + jit->cachedglobal = ofs; + jit->cachedreg = reg; +#else + switch(reg) + { + case REG_NONE: + break; + case REG_S0: + //fstps glob[C] + EmitByte(0xd9);EmitByte(0x1d);EmitAdr(jit->glob + ofs); + break; + default: + STOREREG(reg, jit->glob + ofs); + break; + } +#endif +} + static void *LocalLoc(struct jitstate *jit) { return &jit->code[jit->codesize]; @@ -359,6 +478,9 @@ struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs) case OP_CALL6: case OP_CALL7: case OP_CALL8: + //FIXME: the size of this instruction is going to hurt cache performance if every single function call is expanded into this HUGE CHUNK of gibberish! + //FIXME: consider the feasability of just calling a C function and just jumping to the address it returns. + //save the state in place the rest of the engine can cope with //movl $i, pr_xstatement EmitByte( 0xc7);EmitByte(0x05);EmitAdr(&pr_xstatement);Emit4Byte(i); @@ -721,6 +843,7 @@ struct jitstate *PR_GenerateJit(progfuncs_t *progfuncs) case OP_AND_F: //test floats properly, so we don't get confused with -0.0 + //FIXME: is it feasable to grab the value as an int and test it against 0x7fffffff? //flds glob[A] EmitByte(0xd9); EmitByte(0x05); EmitAdr(glob + op[i].a); diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index 03aa7839a..9dc58c51d 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -1,5 +1,7 @@ #ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS + #endif #define _CRT_NONSTDC_NO_WARNINGS #ifndef AVAIL_ZLIB #ifdef _MSC_VER @@ -34,10 +36,6 @@ typedef unsigned char qbyte; #define PROGSUSED #endif -extern int maxedicts; -extern int maxprogs; -extern int hunksize; - #include "progtype.h" #include "progslib.h" @@ -283,7 +281,7 @@ unsigned int NUM_FOR_EDICT(progfuncs_t *progfuncs, struct edict_s *e); #define GQ_STRING(o) (*(QCC_string_t *)&pr_globals[o]) #define GQ_STRING2(o) ((char*)*(QCC_string_t *)&pr_globals[o]) #define G_FUNCTION(o) (*(func_t *)&pr_globals[o]) -#define G_PROG(o) (*(progsnum_t *)&pr_globals[o]) //simply so it's nice and easy to change... +#define G_PROG(o) G_FLOAT(o) //simply so it's nice and easy to change... #define RETURN_EDICT(e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(e)) @@ -356,8 +354,8 @@ typedef struct prinst_s { int maxallocedstrings; int numallocedstrings; -var(progstate_t *, pr_progstate); -#define pr_progstate prinst->pr_progstate +var(progstate_t *, progstate); +#define pr_progstate prinst->progstate var(progsnum_t, pr_typecurrent); #define pr_typecurrent prinst->pr_typecurrent diff --git a/engine/qclib/progslib.h b/engine/qclib/progslib.h index 25962d455..1c57db167 100644 --- a/engine/qclib/progslib.h +++ b/engine/qclib/progslib.h @@ -181,6 +181,7 @@ typedef struct progexterns_s { unsigned int *sv_num_edicts; //pointer to the engine's edict count. int (*useeditor) (progfuncs_t *prinst, char *filename, int line, int nump, char **parms); //called on syntax errors or step-by-step debugging. + void (*addressablerelocated) (progfuncs_t *progfuncs, char *oldb, char *newb, int oldlen); //called when the progs memory was resized. you must fix up all pointers to globals, strings, fields, addressable blocks. void *user; /*contains the owner's world reference in FTE*/ } progparms_t, progexterns_t; @@ -210,7 +211,7 @@ typedef union eval_s func_t function; int _int; int edict; - progsnum_t prog; //so it can easily be changed + float prog; //so it can easily be changed } eval_t; #endif diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 3a3ab0f16..fa584cc29 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -4921,6 +4921,9 @@ int QCC_canConv(QCC_def_t *from, etype_t to) } } + if (from->type->type == ev_variant) + return 5; + /* if (from->type->type == ev_pointer && from->type->aux_type->type == to) return 1; diff --git a/engine/qclib/qccgui.c b/engine/qclib/qccgui.c index ac805648a..fb45a4f21 100644 --- a/engine/qclib/qccgui.c +++ b/engine/qclib/qccgui.c @@ -4,13 +4,12 @@ #include #include #include +#include #include "qcc.h" #include "gui.h" - - /* ============== LoadFile @@ -281,11 +280,14 @@ typedef struct editor_s { char filename[MAX_PATH]; //abs HWND window; HWND editpane; + pbool modified; + time_t filemodifiedtime; struct editor_s *next; } editor_t; editor_t *editors; +void EditorReload(editor_t *editor); int EditorSave(editor_t *edit); void EditFile(char *name, int line); pbool EditorModified(editor_t *e); @@ -318,7 +320,7 @@ void GenericMenu(WPARAM wParam) break; case IDM_ABOUT: - MessageBox(NULL, "FTE QuakeC Compiler\nWritten by Forethough Entertainment.\nBasically that means it was written by Spike.\n\nIt has a few cool features, like a useful IDE.\n\nSupports:\nPrecompiler (with macros)\nArrays\n+= / -= / *= / /= operations.\nSwitch statements\nfor loops\nLots of optimisations.", "About", 0); + MessageBox(NULL, "FTE QuakeC Compiler\nWritten by Forethough Entertainment.\n\nIt has a few cool features, like a semi-useful IDE.\n\nSupports:\nPrecompiler (with macros)\nArrays\n+= / -= / *= / /= operations.\nSwitch statements\nfor loops\nLots of optimisations.", "About", 0); break; case IDM_CASCADE: @@ -409,7 +411,7 @@ static LONG CALLBACK EditorWndProc(HWND hWnd,UINT message, { case WM_CLOSE: case WM_QUIT: - if (EditorModified(editor)) + if (editor->modified) { switch (MessageBox(hWnd, "Would you like to save?", editor->filename, MB_YESNOCANCEL)) { @@ -478,22 +480,49 @@ static LONG CALLBACK EditorWndProc(HWND hWnd,UINT message, return TRUE; break; case WM_COMMAND: - if (mdibox) - goto gdefault; - EditorMenu(editor, wParam); + if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == editor->editpane) + { + if (!editor->modified) + { + char title[2048]; + CHARRANGE chrg; + + editor->modified = true; + if (EditorModified(editor)) + if (MessageBox(NULL, "warning: file was modified externally. reload?", "Modified!", MB_YESNO) == IDYES) + EditorReload(editor); + + + SendMessage(editor->editpane, EM_EXGETSEL, 0, (LPARAM) &chrg); + if (editor->modified) + sprintf(title, "*%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, chrg.cpMin)); + else + sprintf(title, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, chrg.cpMin)); + SetWindowText(editor->window, title); + } + } + else + { + if (mdibox) + goto gdefault; + EditorMenu(editor, wParam); + } break; case WM_NOTIFY: { NMHDR *nmhdr; SELCHANGE *sel; - char message[2048]; + char title[2048]; nmhdr = (NMHDR *)lParam; switch(nmhdr->code) { case EN_SELCHANGE: sel = (SELCHANGE *)nmhdr; - sprintf(message, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin)); - SetWindowText(editor->window, message); + if (editor->modified) + sprintf(title, "*%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin)); + else + sprintf(title, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin)); + SetWindowText(editor->window, title); break; } } @@ -758,7 +787,7 @@ int Rehighlight(editor_t *edit) InvalidateRect(edit->editpane, NULL, true); InvalidateRect(edit->window, NULL, true); - SendMessage(edit->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE); + SendMessage(edit->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE|ENM_CHANGE); SendMessage(edit->editpane, EM_SETSCROLLPOS, 0, (LPARAM)&scrollpos); SendMessage(edit->editpane, EM_EXSETSEL, 0, (LPARAM) &chrg); @@ -845,11 +874,46 @@ int Rehighlight(editor_t *edit) } #endif +void EditorReload(editor_t *editor) +{ + struct stat sbuf; + int flen; + char *file; + + flen = QCC_FileSize(editor->filename); + if (flen >= 0) + { + file = malloc(flen+1); + QCC_ReadFile(editor->filename, file, flen); + file[flen] = 0; + } + + SendMessage(editor->editpane, EM_SETEVENTMASK, 0, 0); + + /*clear it out*/ + Edit_SetSel(editor->editpane,0,Edit_GetTextLength(editor->editpane)); + Edit_ReplaceSel(editor->editpane,""); + + if (!fl_autohighlight) + { + GUIPrint(editor->editpane, file); + } + else + { + GUIFormattingPrint(editor->editpane, file); + } + free(file); + + editor->modified = false; + stat(editor->filename, &sbuf); + editor->filemodifiedtime = sbuf.st_mtime; + + SendMessage(editor->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE|ENM_CHANGE); +} + void EditFile(char *name, int line) { char title[1024]; - int flen; - char *file; editor_t *neweditor; WNDCLASS wndclass; HMENU menu, menufile, menuhelp, menunavig; @@ -871,8 +935,7 @@ void EditFile(char *name, int line) } } - flen = QCC_FileSize(name); - if (flen == -1) + if (QCC_FileSize(name) == -1) { MessageBox(NULL, "File not found.", "Error", 0); return; @@ -959,23 +1022,7 @@ void EditFile(char *name, int line) return; } - flen = QCC_FileSize(name); - file = malloc(flen+1); - QCC_ReadFile(name, file, flen); - file[flen] = 0; - - SendMessage(neweditor->editpane, EM_SETEVENTMASK, 0, 0); - - if (!fl_autohighlight) - { - GUIPrint(neweditor->editpane, file); - } - else - { - GUIFormattingPrint(neweditor->editpane, file); - } - - SendMessage(neweditor->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE); + EditorReload(neweditor); if (line >= 0) Edit_SetSel(neweditor->editpane, Edit_LineIndex(neweditor->editpane, line), Edit_LineIndex(neweditor->editpane, line+1)); @@ -992,6 +1039,7 @@ void EditFile(char *name, int line) int EditorSave(editor_t *edit) { + struct stat sbuf; int len; char *file; len = Edit_GetTextLength(edit->editpane); @@ -1009,6 +1057,11 @@ int EditorSave(editor_t *edit) } free(file); + /*now whatever is on disk should have the current time*/ + edit->modified = false; + stat(edit->filename, &sbuf); + edit->filemodifiedtime = sbuf.st_mtime; + return true; } void EditorsRun(void) @@ -1046,26 +1099,14 @@ int GUIFileSize(char *fname) return QCC_FileSize(fname); } +/*checks if the file has been modified externally*/ pbool EditorModified(editor_t *e) { - char *buffer; - int elen, flen; - elen = Edit_GetTextLength(e->editpane); - flen = QCC_FileSize(e->filename); - - if (elen != flen) + struct stat sbuf; + stat(e->filename, &sbuf); + if (e->filemodifiedtime != sbuf.st_mtime) return true; - buffer = malloc(elen+flen); - Edit_GetText(e->editpane, buffer, elen); - QCC_ReadFile(e->filename, buffer+elen, flen); - if (memcmp(buffer, buffer+elen, elen)) - { - free(buffer); - return true; - } - free(buffer); - return false; } @@ -1898,6 +1939,41 @@ void RunCompiler(char *args) progexterns_t ext; progfuncs_t funcs; + editor_t *editor; + for (editor = editors; editor; editor = editor->next) + { + if (editor->modified) + { + if (EditorModified(editor)) + { + char msg[1024]; + sprintf(msg, "%s is modified in both memory and on disk. Overwrite external modification? (saying no will reload from disk)", editor->filename); + switch(MessageBox(NULL, msg, "Modification conflict", MB_YESNOCANCEL)) + { + case IDYES: + EditorSave(editor); + break; + case IDNO: + EditorReload(editor); + break; + case IDCANCEL: + break; /*compiling will use whatever is in memory*/ + } + } + else + { + /*not modified on disk, but modified in memory? try and save it, cos we might as well*/ + EditorSave(editor); + } + } + else + { + /*modified on disk but not in memory? just reload it off disk*/ + if (EditorModified(editor)) + EditorReload(editor); + } + } + memset(&funcs, 0, sizeof(funcs)); funcs.parms = &ext; memset(&ext, 0, sizeof(ext)); diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 41259044e..88f685d6f 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -516,7 +516,7 @@ int WriteBodylessFuncs (int handle) { if (d->type->type == ev_function && !d->scope)// function parms are ok { - if (d->initialized != 1 && d->references>0) + if (!(d->initialized & 1) && d->references>0) { SafeWrite(handle, d->name, strlen(d->name)+1); ret++; @@ -1646,9 +1646,9 @@ void QCC_PR_BeginCompilation (void *memory, int memsize) type_float = QCC_PR_NewType("float", ev_float); type_vector = QCC_PR_NewType("vector", ev_vector); type_entity = QCC_PR_NewType("entity", ev_entity); - type_field = QCC_PR_NewType("field", ev_field); - type_function = QCC_PR_NewType("function", ev_function); - type_pointer = QCC_PR_NewType("pointer", ev_pointer); + type_field = QCC_PR_NewType("__field", ev_field); + type_function = QCC_PR_NewType("__function", ev_function); + type_pointer = QCC_PR_NewType("__pointer", ev_pointer); type_integer = QCC_PR_NewType("__integer", ev_integer); type_variant = QCC_PR_NewType("__variant", ev_variant); @@ -1741,7 +1741,7 @@ int QCC_PR_FinishCompilation (void) bodylessfuncs = true; errors = true; } - s_file = NULL; + s_file = 0; // errors = true; } else if (d->initialized==2) diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index feac6c1e8..aa43c38e6 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -951,8 +951,8 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) protocollen++; if (data & DPSND_LARGESOUND) protocollen++; -#ifdef _MSC_VER -#pragma message("NPP_NQWriteByte: this ignores SVC_SOUND from nq mods (nexuiz)") +#ifdef warningmsg +#pragma warningmsg("NPP_NQWriteByte: this ignores SVC_SOUND from nq mods (nexuiz)") #endif ignoreprotocol = true; break; diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 8127701c6..800b7e474 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -24,7 +24,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "sv_sql.h" #endif -#define G_PROG G_FLOAT #define Z_QC_TAG 2 #ifndef CLIENTONLY @@ -64,7 +63,7 @@ cvar_t pr_maxedicts = CVARF("pr_maxedicts", "2048", CVAR_LATCH); cvar_t pr_no_playerphysics = CVARF("pr_no_playerphysics", "0", CVAR_LATCH); cvar_t pr_no_parsecommand = CVARF("pr_no_parsecommand", "0", 0); -cvar_t progs = CVARAF("progs", "", "sv_progs", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROMSERVER); +cvar_t pr_ssqc_progs = CVARAF("progs", "", "sv_progs", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROMSERVER); cvar_t qc_nonetaccess = CVAR("qc_nonetaccess", "0"); //prevent write_... builtins from doing anything. This means we can run any mod, specific to any engine, on the condition that it also has a qw or nq crc. cvar_t pr_overridebuiltins = CVAR("pr_overridebuiltins", "1"); @@ -135,8 +134,8 @@ func_t EndFrameQC; //a common extension qboolean pr_items2; //hipnotic (or was it rogue?) -nqglobalvars_t realpr_nqglobal_struct; -nqglobalvars_t *pr_nqglobal_struct = &realpr_nqglobal_struct; +globalptrs_t realpr_global_ptrs; +globalptrs_t *pr_global_ptrs = &realpr_global_ptrs; progfuncs_t *svprogfuncs; progparms_t svprogparms; @@ -337,6 +336,54 @@ pbool SV_BadField(progfuncs_t *inst, edict_t *foo, const char *keyname, const ch return false; } +void PR_SV_FillWorldGlobals(world_t *w) +{ + w->g.self = pr_global_ptrs->self; + w->g.other = pr_global_ptrs->other; + w->g.force_retouch = pr_global_ptrs->force_retouch; + w->g.physics_mode = pr_global_ptrs->physics_mode; + w->g.frametime = pr_global_ptrs->frametime; + w->g.newmis = pr_global_ptrs->newmis; + w->g.time = pr_global_ptrs->time; +} + +void PR_SSQC_Relocated(progfuncs_t *pr, char *oldb, char *newb, int oldlen) +{ + edict_t *ent; + int i; + union { + globalptrs_t *g; + char **c; + } b; + b.g = pr_global_ptrs; + for (i = 0; i < sizeof(*b.g)/sizeof(*b.c); i++) + { + if (b.c[i] >= oldb && b.c[i] < oldb+oldlen) + b.c[i] += newb - oldb; + } + PR_SV_FillWorldGlobals(&sv.world); + + for (i = 0; i < sv.world.num_edicts; i++) + { + ent = EDICT_NUM(pr, i); + if ((char*)ent->xv >= oldb && (char*)ent->xv < oldb+oldlen) + ent->xv = (extentvars_t*)((char*)ent->xv - oldb + newb); + } + + for (i = 0; sv.strings.model_precache[i]; i++) + { + if (sv.strings.model_precache[i] >= oldb && sv.strings.model_precache[i] < oldb+oldlen) + sv.strings.model_precache[i] += newb - oldb; + } + for (i = 0; i < MAX_CLIENTS; i++) + { + if (svs.clients[i].name >= oldb && svs.clients[i].name < oldb+oldlen) + svs.clients[i].name += newb - oldb; + if (svs.clients[i].team >= oldb && svs.clients[i].team < oldb+oldlen) + svs.clients[i].team += newb - oldb; + } +} + //int QCEditor (char *filename, int line, int nump, char **parms); void QC_Clear(void); builtin_t pr_builtin[]; @@ -468,6 +515,10 @@ void Q_SetProgsParms(qboolean forcompiler) svprogparms.useeditor = QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms); + //until its properly tested + if (pr_ssqc_memsize.ival == -2) + svprogparms.addressablerelocated = PR_SSQC_Relocated; + if (!svprogfuncs) { sv.world.progs = svprogfuncs = InitProgs(&svprogparms); @@ -475,7 +526,7 @@ void Q_SetProgsParms(qboolean forcompiler) sv.world.Event_Touch = SVPR_Event_Touch; sv.world.Event_Think = SVPR_Event_Think; sv.world.Event_Sound = SVQ1_StartSound; - sv.world.GetCModel = SVPR_GetCModel; + sv.world.Get_CModel = SVPR_GetCModel; PRSV_ClearThreads(); PR_fclose_progs(svprogfuncs); @@ -524,6 +575,7 @@ void PR_Deinit(void) void PR_LoadGlabalStruct(void) { + static float svphysicsmode = 2; static float writeonly; static float dimension_send_default; static float zero_default; @@ -534,13 +586,13 @@ void PR_LoadGlabalStruct(void) static vec3_t input_movevalues_default; int i; int *v; - nqglobalvars_t *pr_globals = pr_nqglobal_struct; -#define globalfloat(need,name) ((nqglobalvars_t*)pr_nqglobal_struct)->name = (float *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find \""#name"\" export in progs\n"); -#define globalint(need,name) ((nqglobalvars_t*)pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); -#define globalstring(need,name) ((nqglobalvars_t*)pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); -#define globalvec(need,name) ((nqglobalvars_t*)pr_globals)->V_##name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->V_##name) SV_Error("Could not find export \""#name"\" in progs\n"); -#define globalvec_(need,name) ((nqglobalvars_t*)pr_globals)->name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !((nqglobalvars_t*)pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); -#define globalfunc(need,name) ((nqglobalvars_t*)pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (!((nqglobalvars_t*)pr_globals)->name) {static func_t stripped##name; stripped##name = PR_FindFunction(svprogfuncs, #name, 0); if (stripped##name) ((nqglobalvars_t*)pr_globals)->name = &stripped##name; else if (need) SV_Error("Could not find function \""#name"\" in progs\n"); } + globalptrs_t *pr_globals = pr_global_ptrs; +#define globalfloat(need,name) (pr_globals)->name = (float *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) SV_Error("Could not find \""#name"\" export in progs\n"); +#define globalint(need,name) (pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); +#define globalstring(need,name) (pr_globals)->name = (int *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); +#define globalvec(need,name) (pr_globals)->V_##name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->V_##name) SV_Error("Could not find export \""#name"\" in progs\n"); +#define globalvec_(need,name) (pr_globals)->name = (vec3_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (need && !(pr_globals)->name) SV_Error("Could not find export \""#name"\" in progs\n"); +#define globalfunc(need,name) (pr_globals)->name = (func_t *)PR_FindGlobal(svprogfuncs, #name, 0, NULL); if (!(pr_globals)->name) {static func_t stripped##name; stripped##name = PR_FindFunction(svprogfuncs, #name, 0); if (stripped##name) (pr_globals)->name = &stripped##name; else if (need) SV_Error("Could not find function \""#name"\" in progs\n"); } // globalint(pad); globalint (true, self); //we need the qw ones, but any in standard quake and not quakeworld, we don't really care about. globalint (true, other); @@ -598,9 +650,9 @@ void PR_LoadGlabalStruct(void) memset(&evalc_pitch_speed, 0, sizeof(evalc_pitch_speed)); for (i = 0; i < NUM_SPAWN_PARMS; i++) - spawnparamglobals[i] = (float *)PR_FindGlobal(svprogfuncs, va("parm%i", i+1), 0, NULL); + pr_global_ptrs->spawnparamglobals[i] = (float *)PR_FindGlobal(svprogfuncs, va("parm%i", i+1), 0, NULL); -#define ensureglobal(name,var) if (!((nqglobalvars_t*)pr_globals)->name) ((nqglobalvars_t*)pr_globals)->name = &var; +#define ensureglobal(name,var) if (!(pr_globals)->name) (pr_globals)->name = &var; // make sure these entries are always valid pointers ensureglobal(dimension_send, dimension_send_default); @@ -613,22 +665,22 @@ void PR_LoadGlabalStruct(void) ensureglobal(input_buttons, input_buttons_default); // qtest renames and missing variables - if (!((nqglobalvars_t*)pr_globals)->V_trace_plane_normal) + if (!(pr_globals)->V_trace_plane_normal) { - ((nqglobalvars_t*)pr_globals)->V_trace_plane_normal = (vec3_t *)PR_FindGlobal(svprogfuncs, "trace_normal", 0, NULL); - if (!((nqglobalvars_t*)pr_globals)->V_trace_plane_normal) + (pr_globals)->V_trace_plane_normal = (vec3_t *)PR_FindGlobal(svprogfuncs, "trace_normal", 0, NULL); + if (!(pr_globals)->V_trace_plane_normal) SV_Error("Could not find export trace_plane_normal in progs\n"); } - if (!((nqglobalvars_t*)pr_globals)->V_trace_endpos) + if (!(pr_globals)->V_trace_endpos) { - ((nqglobalvars_t*)pr_globals)->V_trace_endpos = (vec3_t *)PR_FindGlobal(svprogfuncs, "trace_impact", 0, NULL); - if (!((nqglobalvars_t*)pr_globals)->V_trace_endpos) + (pr_globals)->V_trace_endpos = (vec3_t *)PR_FindGlobal(svprogfuncs, "trace_impact", 0, NULL); + if (!(pr_globals)->V_trace_endpos) SV_Error("Could not find export trace_endpos in progs\n"); } - if (!((nqglobalvars_t*)pr_globals)->trace_fraction) + if (!(pr_globals)->trace_fraction) { - ((nqglobalvars_t*)pr_globals)->trace_fraction = (float *)PR_FindGlobal(svprogfuncs, "trace_frac", 0, NULL); - if (!((nqglobalvars_t*)pr_globals)->trace_fraction) + (pr_globals)->trace_fraction = (float *)PR_FindGlobal(svprogfuncs, "trace_frac", 0, NULL); + if (!(pr_globals)->trace_fraction) SV_Error("Could not find export trace_fraction in progs\n"); } ensureglobal(serverflags, zero_default); @@ -641,6 +693,7 @@ void PR_LoadGlabalStruct(void) ensureglobal(trace_plane_dist, writeonly); ensureglobal(trace_inopen, writeonly); ensureglobal(trace_inwater, writeonly); + ensureglobal(physics_mode, svphysicsmode); pr_global_struct->dimension_send = 255; pr_global_struct->serverflags = 0; @@ -676,20 +729,15 @@ void PR_LoadGlabalStruct(void) EndFrameQC = PR_FindFunction (svprogfuncs, "EndFrame", PR_ANY); v = (int *)PR_globals(svprogfuncs, PR_CURRENT); - QC_AddSharedVar(svprogfuncs, (int *)((nqglobalvars_t*)pr_nqglobal_struct)->self-v, 1); - QC_AddSharedVar(svprogfuncs, (int *)((nqglobalvars_t*)pr_nqglobal_struct)->other-v, 1); - QC_AddSharedVar(svprogfuncs, (int *)((nqglobalvars_t*)pr_nqglobal_struct)->time-v, 1); + QC_AddSharedVar(svprogfuncs, (int *)(pr_global_ptrs)->self-v, 1); + QC_AddSharedVar(svprogfuncs, (int *)(pr_global_ptrs)->other-v, 1); + QC_AddSharedVar(svprogfuncs, (int *)(pr_global_ptrs)->time-v, 1); pr_items2 = !!PR_FindGlobal(svprogfuncs, "items2", 0, NULL); SV_ClearQCStats(); - sv.world.g.self = pr_nqglobal_struct->self; - sv.world.g.other = pr_nqglobal_struct->other; - sv.world.g.force_retouch = pr_nqglobal_struct->force_retouch; - sv.world.g.frametime = pr_nqglobal_struct->frametime; - sv.world.g.newmis = pr_nqglobal_struct->newmis; - sv.world.g.time = pr_nqglobal_struct->time; + PR_SV_FillWorldGlobals(&sv.world); /*Hexen2 has lots of extra stats, which I don't want special support for, so list them here and send them as for csqc*/ if (progstype == PROG_H2) @@ -1101,7 +1149,7 @@ void PR_Init(void) Cvar_Register (&temp1, cvargroup_progs); Cvar_Register (&noexit, cvargroup_progs); - Cvar_Register (&progs, cvargroup_progs); + Cvar_Register (&pr_ssqc_progs, cvargroup_progs); Cvar_Register (&pr_compatabilitytest, cvargroup_progs); Cvar_Register (&qc_nonetaccess, cvargroup_progs); @@ -1202,13 +1250,15 @@ void Q_InitProgs(void) } } - if (*progs.string && strlen(progs.string)<64 && *progs.string != '*') //a * is a special case to not load a q2 dll. + /*if pr_ssqc_progs cvar is set, override the default*/ + if (*pr_ssqc_progs.string && strlen(pr_ssqc_progs.string)<64 && *pr_ssqc_progs.string != '*') //a * is a special case to not load a q2 dll. { - Q_strncpyz(addons, progs.string, MAX_QPATH); + Q_strncpyz(addons, pr_ssqc_progs.string, MAX_QPATH); COM_DefaultExtension(addons, ".dat", sizeof(addons)); } oldprnum= AddProgs(addons); + /*try to load qwprogs.dat if we didn't manage to load one yet*/ if (oldprnum < 0 && strcmp(addons, "qwprogs.dat")) { #ifndef SERVERONLY @@ -1218,6 +1268,7 @@ void Q_InitProgs(void) oldprnum= AddProgs("qwprogs.dat"); } + /*try to load qwprogs.dat if we didn't manage to load one yet*/ if (oldprnum < 0 && strcmp(addons, "progs.dat")) { #ifndef SERVERONLY @@ -2804,7 +2855,7 @@ already running on that entity/channel pair. An attenuation of 0 will play full volume everywhere in the level. Larger attenuations will drop off. -pitchadj is a number between -128 and 127. values greater than 0 will result in a higher pitch, less than 0 gives lower pitch. +pitchadj is a percent. values greater than 100 will result in a lower pitch, less than 100 gives a higher pitch. ================= */ @@ -4423,7 +4474,7 @@ void QCBUILTIN PF_WriteAngle (progfuncs_t *prinst, struct globalvars_s *pr_globa client_t *cl = Write_GetClient(); if (!cl) return; - ClientReliableCheckBlock(cl, 1); + ClientReliableCheckBlock(cl, 4); ClientReliableWrite_Angle(cl, G_FLOAT(OFS_PARM1)); } else @@ -4881,8 +4932,8 @@ void QCBUILTIN PF_setspawnparms (progfuncs_t *prinst, struct globalvars_s *pr_gl client = svs.clients + (i-1); for (i=0 ; i< NUM_SPAWN_PARMS ; i++) - if (spawnparamglobals[i]) - *spawnparamglobals[i] = client->spawn_parms[i]; + if (pr_global_ptrs->spawnparamglobals[i]) + *pr_global_ptrs->spawnparamglobals[i] = client->spawn_parms[i]; } /* @@ -6649,6 +6700,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s switch(efnum) { case ce_rain: + /*this effect is meant to be persistant (endeffect is never used)*/ //min = G_VECTOR(OFS_PARM1); //max = G_VECTOR(OFS_PARM2); //size = G_VECTOR(OFS_PARM3); @@ -6662,6 +6714,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s return; break; case ce_snow: + /*this effect is meant to be persistant (endeffect is never used)*/ //min = G_VECTOR(OFS_PARM1); //max = G_VECTOR(OFS_PARM2); //flags = G_FLOAT(OFS_PARM3); @@ -6672,6 +6725,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s return; break; case ce_fountain: + /*this effect is meant to be persistant (endeffect is never used)*/ //org = G_VECTOR(OFS_PARM1); //angle = G_VECTOR(OFS_PARM2); //dir = G_VECTOR(OFS_PARM3); @@ -6682,6 +6736,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s return; break; case ce_quake: + /*this effect is meant to be persistant*/ org = G_VECTOR(OFS_PARM1); //radius = G_FLOAT(OFS_PARM2); /*discard: always 500/3 */ @@ -6837,7 +6892,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s //angle = G_VECTOR(OFS_PARM3); /*discard: angle is a function of the dir*/ //avelocity = G_VECTOR(OFS_PARM4);/*discard: avelocity is a function of the dir*/ - /*FIXME: persistant until removed*/ + /*FIXME: meant to be persistant until removed*/ if (h2customtents[efnum] != -1) { SV_CustomTEnt_Spawn(h2customtents[efnum], org, NULL, 1, dir); @@ -6867,121 +6922,14 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s } Con_Printf("FTE-H2 FIXME: Effect %i doesn't have an effect registered\nTell Spike!\n", efnum); - -#if 0 - - switch((int)G_FLOAT(OFS_PARM0)) - { - case 4: //white_smoke - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/whtsmk1.spr"), 0, 5, 1/G_FLOAT(OFS_PARM3)); - break; - case 6: //yellowspark - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/spark.spr"), 0, 10, 20); - break; - case 7: //sm_circle - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/fcircle.spr"), 0, 6, 20); - break; - case 9: //sm_white_flash - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/sm_white.spr"), 0, 3, 20); - break; - case 11: //yellowred_flash - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/yr_flsh.spr"), 0, 21, 20); - break; - case 13: //sm_blue_flash - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/bluflash.spr"), 0, 5, 20); - break; - case 14: //red_flash - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/redspt.spr"), 0, 5, 20); - break; - case 15: //sm_explosion - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/sm_expld.spr"), 0, 12, 20); - break; - case 16: //lg_explosion - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/bg_expld.spr"), 0, 12, 20); - break; - case 17: //floor_explosion - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/fl_expld.spr"), 0, 20, 20); - break; - case 20: //green_smoke - //parm1 = vel - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/grnsmk1.spr"), 0, 8, 1/G_FLOAT(OFS_PARM3)); - break; - case 24: //redspark - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/rspark.spr"), 0, 10, 20); - break; - case 25: //greenspark - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/gspark.spr"), 0, 10, 20); - break; - case 26: //telesmk1 - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/telesmk1.spr"), 0, 4, 1/G_FLOAT(OFS_PARM3)); - break; - case 28: //icehit - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/icehit.spr"), 0, 6, 20); - break; - case 33: //new_explosion - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/gen_expl.spr"), 0, 14, 20); - break; - case 34: //magic_missile_explosion - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/mm_explod.spr"), 0, 50, 20); - break; - case 42: //flamestream - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/flamestr.spr"), 0, 12, 20); - break; - case 45: //bldrn_expl - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/xplsn_1.spr"), 0, 7, 20); - break; - case 47: //acid_hit - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/axplsn_2.spr"), 0, 14, 20); - break; - case 48: //firewall_small - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/firewal1.spr"), 0, 18, 20); - break; - case 49: //firewall_medium - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/firewal5.spr"), 0, 30, 20); - break; - case 50: //firewall_large - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/firewal4.spr"), 0, 29, 20); - break; - case 54: //fboom - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/fboom.spr"), 0, 14, 20); - break; - case 56: //bomb - SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/pow.spr"), 0, 6, 20); - break; - case 5: //bluespark - case 43: //snow - case 46: //acid_muzzfl - case 51: //lball_expl - case 52: //acid_splat - case 53: //acid_expl - case 57: //brn_bounce - case 58: //lshock - case 38: //teleporterpuffs - case 39: //teleporterbody - case 62: //onfire - break; - - - case 40: //boneshard -// SV_Effect(G_VECTOR(OFS_PARM1), PF_precache_model_Internal(prinst, "models/boneshot.mdl"), 0, 50, 20); -// break; - - case 2: //fountain - case 55: //chunk - Con_DPrintf("Start unsupported effect %i\n", (int)G_FLOAT(OFS_PARM0)); - break; - - - default: - Con_Printf("Start effect %i\n", (int)G_FLOAT(OFS_PARM0)); - break; - } -#endif } static void QCBUILTIN PF_h2endeffect(progfuncs_t *prinst, struct globalvars_s *pr_globals) { - Con_DPrintf("Stop effect %i\n", (int)G_FLOAT(OFS_PARM0)); + int ign = G_FLOAT(OFS_PARM0); + int index = G_FLOAT(OFS_PARM1); + + Con_DPrintf("Stop effect %i\n", index); } static void QCBUILTIN PF_h2rain_go(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -6994,7 +6942,7 @@ static void QCBUILTIN PF_h2rain_go(progfuncs_t *prinst, struct globalvars_s *pr_ float colour = G_FLOAT(OFS_PARM4); float count = G_FLOAT(OFS_PARM5); */ - Con_DPrintf("rain go\n"); + Con_DPrintf("FTE-H2 FIXME: rain_go not implemented\n"); } static void QCBUILTIN PF_h2StopSound(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -7010,7 +6958,7 @@ static void QCBUILTIN PF_h2StopSound(progfuncs_t *prinst, struct globalvars_s *p static void QCBUILTIN PF_h2updatesoundpos(progfuncs_t *prinst, struct globalvars_s *pr_globals) { - Con_DPrintf("updatesoundpos\n"); + Con_DPrintf("FTE-H2 FIXME: updatesoundpos not implemented\n"); } static void QCBUILTIN PF_h2whiteflash(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -7019,7 +6967,7 @@ static void QCBUILTIN PF_h2whiteflash(progfuncs_t *prinst, struct globalvars_s * broadcast a stuffcmd, I guess, to flash the screen white Only seen this occur once: after killing pravus. */ - Con_DPrintf("white flash\n"); + Con_DPrintf("FTE-H2 FIXME: whiteflash not implemented\n"); } static void QCBUILTIN PF_h2getstring(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -7150,8 +7098,8 @@ static void QCBUILTIN PF_CustomTEnt(progfuncs_t *prinst, struct globalvars_s *pr static void QCBUILTIN PF_sv_particleeffectnum(progfuncs_t *prinst, struct globalvars_s *pr_globals) { #ifdef PEXT_CSQC -#ifdef _MSC_VER -#pragma message("PF_sv_particleeffectnum: which effect index values to use?") +#ifdef warningmsg +#pragma warningmsg("PF_sv_particleeffectnum: which effect index values to use?") #endif char *efname = PR_GetStringOfs(prinst, OFS_PARM0); G_FLOAT(OFS_RETURN) = COM_Effectinfo_ForName(efname); @@ -7338,14 +7286,19 @@ static void QCBUILTIN PF_Fork(progfuncs_t *prinst, struct globalvars_s *pr_globa { qcstate_t *state; struct qcthread_s *thread; + float sleeptime; + if (*svprogfuncs->callargc >= 1) + sleeptime = G_FLOAT(OFS_PARM0); + else + sleeptime = 0; thread = svprogfuncs->Fork(svprogfuncs); state = svprogfuncs->parms->memalloc(sizeof(qcstate_t)); state->next = qcthreads; qcthreads = state; - state->resumetime = sv.time; + state->resumetime = sv.time + sleeptime; state->self = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, pr_global_struct->self)); state->other = NUM_FOR_EDICT(svprogfuncs, PROG_TO_EDICT(svprogfuncs, pr_global_struct->other)); state->thread = thread; @@ -8250,8 +8203,8 @@ static void QCBUILTIN PF_sv_gettaginfo(progfuncs_t *prinst, struct globalvars_s if (ent->xv->tag_entity) { -#ifdef _MSC_VER - #pragma message("PF_sv_gettaginfo: This function doesn't honour attachments") +#ifdef warningmsg + #pragma warningmsg("PF_sv_gettaginfo: This function doesn't honour attachments") #endif Con_Printf("PF_sv_gettaginfo doesn't support attachments\n"); } @@ -8300,8 +8253,8 @@ static void QCBUILTIN PF_runclientphys(progfuncs_t *prinst, struct globalvars_s unsigned int msecs; edict_t *ent = G_EDICT(prinst, OFS_PARM0); edict_t *touched; - if (pr_nqglobal_struct->clientcommandframe) - pmove.sequence = *pr_nqglobal_struct->clientcommandframe; + if (pr_global_ptrs->clientcommandframe) + pmove.sequence = *pr_global_ptrs->clientcommandframe; else pmove.sequence = 0; if (host_client && host_client->edict == ent) diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index 322b9ce44..510ef1fb6 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -1368,7 +1368,7 @@ qboolean PR_LoadQ1QVM(void) sv.world.Event_Touch = Q1QVM_Event_Touch; sv.world.Event_Think = Q1QVM_Event_Think; - sv.world.GetCModel = SVPR_GetCModel; + sv.world.Get_CModel = SVPR_GetCModel; sv.world.num_edicts = 0; //we're not ready for most of the builtins yet sv.world.max_edicts = 0; //so clear these out, just in case @@ -1414,12 +1414,12 @@ qboolean PR_LoadQ1QVM(void) //WARNING: global is not remapped yet... //This code is written evilly, but works well enough -#define globalint(required, name) pr_nqglobal_struct->name = (int*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) //the logic of this is somewhat crazy -#define globalfloat(required, name) pr_nqglobal_struct->name = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) -#define globalstring(required, name) pr_nqglobal_struct->name = (string_t*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) -#define globalvec(required, name) pr_nqglobal_struct->V_##name = (vec3_t*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) -#define globalfunc(required, name) pr_nqglobal_struct->name = (int*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) -#define globalfloatnull(required, name) pr_nqglobal_struct->name = NULL +#define globalint(required, name) pr_global_ptrs->name = (int*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) //the logic of this is somewhat crazy +#define globalfloat(required, name) pr_global_ptrs->name = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) +#define globalstring(required, name) pr_global_ptrs->name = (string_t*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) +#define globalvec(required, name) pr_global_ptrs->V_##name = (vec3_t*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) +#define globalfunc(required, name) pr_global_ptrs->name = (int*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)&gd->global->name) +#define globalfloatnull(required, name) pr_global_ptrs->name = NULL globalint (true, self); //we need the qw ones, but any in standard quake and not quakeworld, we don't really care about. globalint (true, other); globalint (true, world); @@ -1463,15 +1463,15 @@ qboolean PR_LoadQ1QVM(void) globalfunc (false, SetNewParms); globalfunc (false, SetChangeParms); - pr_nqglobal_struct->trace_surfaceflags = &writable; - pr_nqglobal_struct->trace_endcontents = &writable; - pr_nqglobal_struct->dimension_send = &dimensionsend; + pr_global_ptrs->trace_surfaceflags = &writable; + pr_global_ptrs->trace_endcontents = &writable; + pr_global_ptrs->dimension_send = &dimensionsend; dimensionsend = 255; for (i = 0; i < 16; i++) - spawnparamglobals[i] = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)(&gd->global->parm1 + i)); + pr_global_ptrs->spawnparamglobals[i] = (float*)((char*)VM_MemoryBase(q1qvm)+(qintptr_t)(&gd->global->parm1 + i)); for (; i < NUM_SPAWN_PARMS; i++) - spawnparamglobals[i] = NULL; + pr_global_ptrs->spawnparamglobals[i] = NULL; sv.world.progs = &q1qvmprogfuncs; diff --git a/engine/server/progdefs.h b/engine/server/progdefs.h index d14afbd7a..c2802d24a 100644 --- a/engine/server/progdefs.h +++ b/engine/server/progdefs.h @@ -35,6 +35,7 @@ typedef struct globalvars_s } param[8]; } globalvars_t; +#define NUM_SPAWN_PARMS 64 typedef struct nqglobalvars_s { int *self; @@ -81,13 +82,14 @@ typedef struct nqglobalvars_s float *cycle_wrapped; float *dimension_send; - + float *physics_mode; float *clientcommandframe; float *input_timelength; vec3_t *input_angles; vec3_t *input_movevalues; float *input_buttons; -} nqglobalvars_t; + float *spawnparamglobals[NUM_SPAWN_PARMS]; +} globalptrs_t; #define P_VEC(v) (pr_global_struct->V_##v) @@ -229,7 +231,7 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloat(glow_size);\ comfieldfloat(glow_color);\ comfieldfloat(glow_trail);\ - comfieldvector(color);\ + comfieldvector(color);/*Hexen2 has a .float color, the warnings should be benign*/ \ comfieldfloat(light_lev);\ comfieldfloat(style);\ comfieldfloat(pflags);\ diff --git a/engine/server/progs.h b/engine/server/progs.h index 06425e27a..ce09a542b 100644 --- a/engine/server/progs.h +++ b/engine/server/progs.h @@ -26,9 +26,6 @@ struct edict_s; #define MAX_PROGS 64 #define MAXADDONS 16 -#define NUM_SPAWN_PARMS 64 //moved from server.h because of include ordering :(. - - void SVQ1_CvarChanged(cvar_t *var); #define NewGetEdictFieldValue GetEdictFieldValue void Q_SetProgsParms(qboolean forcompiler); @@ -104,12 +101,9 @@ typedef struct edict_s #include "progslib.h" #undef pr_global_struct -//#define pr_nqglobal_struct *((nqglobalvars_t*)pr_globals) -#define pr_global_struct *pr_nqglobal_struct +#define pr_global_struct *pr_global_ptrs -float *spawnparamglobals[NUM_SPAWN_PARMS]; - -extern nqglobalvars_t *pr_nqglobal_struct; +extern globalptrs_t *pr_global_ptrs; extern progfuncs_t *svprogfuncs; //instance extern progparms_t svprogparms; diff --git a/engine/server/savegame.c b/engine/server/savegame.c index 11af2289b..082a1a1cd 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -330,12 +330,12 @@ void SV_Loadgame_f(void) if (version == 5) { progstype = PROG_NQ; - Cvar_Set ("progs", "progs.dat"); //NQ's progs. + Cvar_SetVar (pr_ssqc_progs, "progs.dat"); //NQ's progs. } else { progstype = PROG_QW; - Cvar_Set ("progs", "spprogs.dat"); //zquake's single player qw progs. + Cvar_SetVar (&pr_ssqc_progs, "spprogs.dat"); //zquake's single player qw progs. } pt = 0; } @@ -722,8 +722,8 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea e2->_float = 1; for (j=0 ; j< NUM_SPAWN_PARMS ; j++) { - if (spawnparamglobals[j]) - *spawnparamglobals[j] = host_client->spawn_parms[j]; + if (pr_global_ptrs->spawnparamglobals[j]) + *pr_global_ptrs->spawnparamglobals[j] = host_client->spawn_parms[j]; } pr_global_struct->time = sv.world.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); @@ -911,7 +911,6 @@ void SV_Savegame (char *savename) extern cvar_t temp1; extern cvar_t noexit; extern cvar_t pr_maxedicts; - extern cvar_t progs; client_t *cl; @@ -989,7 +988,7 @@ void SV_Savegame (char *savename) VFS_PRINTF (f, "temp1 \"%s\"\n", temp1.string); VFS_PRINTF (f, "noexit \"%s\"\n", noexit.string); VFS_PRINTF (f, "pr_maxedicts\t \"%s\"\n", pr_maxedicts.string); - VFS_PRINTF (f, "progs \"%s\"\n", progs.string); + VFS_PRINTF (f, "progs \"%s\"\n", pr_ssqc_progs.string); VFS_PRINTF (f, "set nextserver \"%s\"\n", Cvar_Get("nextserver", "", 0, "")->string); VFS_PRINTF (f, "}\n"); diff --git a/engine/server/server.h b/engine/server/server.h index a82eb3b23..11324a715 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -515,6 +515,7 @@ typedef struct client_s SCP_QUAKE3, //all the below are considered netquake clients. SCP_NETQUAKE, + SCP_FITZ666, SCP_DARKPLACES6, SCP_DARKPLACES7 //extra prediction stuff //note, nq is nq+ @@ -842,10 +843,10 @@ typedef struct //define EF_BRIGHTFIELD 1 //define EF_MUZZLEFLASH 2 -#define EF_BRIGHTLIGHT 4 -#define EF_DIMLIGHT 8 +//#define EF_BRIGHTLIGHT (1<<2) +//#define EF_DIMLIGHT (1<<4) -#define EF_FULLBRIGHT 512 +//#define EF_FULLBRIGHT 512 #define SPAWNFLAG_NOT_EASY (1<<8) @@ -895,6 +896,7 @@ extern cvar_t sv_antilag_frac; extern netadr_t master_adr[MAX_MASTERS]; // address of the master server +extern cvar_t pr_ssqc_progs; extern cvar_t spawn; extern cvar_t teamplay; extern cvar_t deathmatch; diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 884904ad4..66c7dfa9d 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -41,32 +41,6 @@ cvar_t sv_cheats = SCVARF("sv_cheats", "0", CVAR_LATCH); extern cvar_t sv_public; -void deleetstring(char *match, char *leet) -{ - char *s = match; - char *s2 = leet; - while(*s2) - { - *s = *s2 & ~128; - s2++; - if (*s == '3') - *s = 'e'; - else if (*s == '4') - *s = 'a'; - else if (*s == '1' || *s == '7') - *s = 'l'; - else if (*s >= 18 && *s < 27) - *s = *s - 18 + '0'; - else if (*s >= 'A' && *s <= 'Z') - *s = *s - 'A' + 'a'; - else if (*s == ' ' || *s == '~') - continue; - s++; - } - *s = '\0'; - -} - //generic helper function for naming players. client_t *SV_GetClientForString(char *name, int *id) { @@ -511,7 +485,15 @@ void SV_Map_f (void) issamelevel = true; if (!*level) + { + sv.mapchangelocked = true; + if (Cmd_AliasExist("startmap_dm", RESTRICT_LOCAL)) + { + Cbuf_AddText("startmap_dm", Cmd_ExecLevel); + return; + } Q_strncpyz(level, "start", sizeof(level)); + } //override the startspot Q_strncpyz(spot, Info_ValueForKey(svs.info, "*startspot"), sizeof(spot)); diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 667622be6..db0723727 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -582,7 +582,7 @@ void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qb evenmorebits |= U_ENTITYDBL2; if (to->number >= 2048) - SV_Error ("Entity number >= 2048"); + return; } else evenmorebits |= U_ENTITYDBL; @@ -872,10 +872,10 @@ void SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t * void SVDP_EmitEntityDelta(entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean isnew) { int bits; - if (!isnew && !memcmp(from, to, sizeof(entity_state_t))) - { - return; //didn't change - } +// if (!isnew && !memcmp(from, to, sizeof(entity_state_t))) +// { +// return; //didn't change +// } bits = 0; if (isnew) @@ -883,6 +883,10 @@ void SVDP_EmitEntityDelta(entity_state_t *from, entity_state_t *to, sizebuf_t *m bits |= E5_FULLUPDATE; } + bits |= E5_MODEL; + bits |= E5_ORIGIN; + bits |= E5_FRAME; + if (!VectorEquals(from->origin, to->origin)) bits |= E5_ORIGIN; if (!VectorEquals(from->angles, to->angles)) @@ -1049,14 +1053,14 @@ void SVDP_EmitEntitiesUpdate (client_t *client, packet_entities_t *to, sizebuf_t client->netchan.incoming_sequence++; // this is the frame that we are going to delta update from - fromframe = &client->frameunion.frames[(client->netchan.incoming_sequence-2) & UPDATE_MASK]; + fromframe = &client->frameunion.frames[client->delta_sequence & UPDATE_MASK]; from = &fromframe->entities; oldmax = from->num_entities; // Con_Printf ("frame %i\n", client->netchan.incoming_sequence); MSG_WriteByte(msg, svcdp_entities); - MSG_WriteLong(msg, 0); + MSG_WriteLong(msg, client->netchan.incoming_sequence); if (client->protocol == SCP_DARKPLACES7) MSG_WriteLong(msg, client->last_sequence); @@ -1841,7 +1845,6 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t * ClientReliableWrite_Short(client, pflags); if (pflags & 1) ClientReliableWrite_Short(client, client->otherclientsknown[j].vweap); - ClientReliable_FinishWrite(client); } } } @@ -2256,8 +2259,8 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli } } - if (state->effects & 0x00400000) //DP's EF_LOWPRECISION - state->effects &= ~0x00400000; //we don't support it, nor does dp any more. strip it. + if (state->effects & DPEF_LOWPRECISION) + state->effects &= DPEF_LOWPRECISION; //we don't support it, nor does dp any more. strip it. if (state->effects & EF_FULLBRIGHT) //wrap the field for fte clients (this is horrible) { @@ -2538,14 +2541,10 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs, //the entity would mess up the client and possibly disconnect them. //FIXME: add an option to drop clients... entity fog could be killed in this way. - if (!ISDPCLIENT(client)) - { - if (e >= client->max_net_ents) - continue; - if (ent->v->modelindex >= client->maxmodels) - continue; - } - + if (e >= client->max_net_ents) + continue; + if (ent->v->modelindex >= client->maxmodels) + continue; #ifdef DEPTHOPTIMISE if (clent) { diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index e9db572be..2162bc5eb 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -380,21 +380,21 @@ void SV_SaveSpawnparms (qboolean dontsave) Q1QVM_SetChangeParms(); for (j=0 ; jspawn_parms[j] = *spawnparamglobals[j]; + if (pr_global_ptrs->spawnparamglobals[j]) + host_client->spawn_parms[j] = *pr_global_ptrs->spawnparamglobals[j]; else host_client->spawn_parms[j] = 0; } } #endif - else if (pr_nqglobal_struct->SetChangeParms) + else if (pr_global_ptrs->SetChangeParms) { pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, host_client->edict); PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetChangeParms); for (j=0 ; jspawn_parms[j] = *spawnparamglobals[j]; + if (pr_global_ptrs->spawnparamglobals[j]) + host_client->spawn_parms[j] = *pr_global_ptrs->spawnparamglobals[j]; else host_client->spawn_parms[j] = 0; } @@ -414,8 +414,8 @@ void SV_SaveSpawnparms (qboolean dontsave) host_client->deaths=0; for (j=0 ; jspawnparamglobals[j]) + rs.parm[j] = *pr_global_ptrs->spawnparamglobals[j]; else rs.parm[j] = 0; } @@ -612,7 +612,6 @@ clients along with it. This is only called from the SV_Map_f() function. ================ */ -extern cvar_t progs; void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean usecinematic) { func_t f; @@ -713,6 +712,11 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us r_worldentity.model = NULL; if (0) cls.state = ca_connected; + if (R_PreNewMap) + R_PreNewMap(); +#ifdef VM_CG + CG_Stop(); +#endif #endif #ifdef Q3SERVER @@ -956,7 +960,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us else #endif #ifdef Q2SERVER - if ((sv.world.worldmodel->fromgame == fg_quake2 || sv.world.worldmodel->fromgame == fg_quake3) && !*progs.string && SVQ2_InitGameProgs()) //these are the rules for running a q2 server + if ((sv.world.worldmodel->fromgame == fg_quake2 || sv.world.worldmodel->fromgame == fg_quake3) && !*pr_ssqc_progs.string && SVQ2_InitGameProgs()) //these are the rules for running a q2 server newgametype = GT_QUAKE2; //we loaded the dll else #endif @@ -1250,9 +1254,9 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us } else { - if (pr_nqglobal_struct->coop && coop.value) + if (pr_global_ptrs->coop && coop.value) pr_global_struct->coop = coop.value; - else if (pr_nqglobal_struct->deathmatch) + else if (pr_global_ptrs->deathmatch) pr_global_struct->deathmatch = deathmatch.value; } @@ -1497,8 +1501,8 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us // copy spawn parms out of the client_t for (j=0 ; j< NUM_SPAWN_PARMS ; j++) { - if (spawnparamglobals[j]) - *spawnparamglobals[j] = host_client->spawn_parms[j]; + if (pr_global_ptrs->spawnparamglobals[j]) + *pr_global_ptrs->spawnparamglobals[j] = host_client->spawn_parms[j]; } SV_SetUpClientEdict(host_client, sv_player); diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index ce98d6cdb..7cda657ad 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -124,19 +124,19 @@ cvar_t allow_download_anymap = CVAR("allow_download_pakmaps", "0"); cvar_t allow_download_pakcontents = CVAR("allow_download_pakcontents", "1"); cvar_t allow_download_root = CVAR("allow_download_root", "0"); cvar_t allow_download_textures = CVAR("allow_download_textures", "1"); -cvar_t allow_download_pk3s = CVAR("allow_download_pk3s", "1"); +cvar_t allow_download_packages = CVAR("allow_download_packages", "1"); cvar_t allow_download_wads = CVAR("allow_download_wads", "1"); cvar_t allow_download_configs = CVAR("allow_download_configs", "0"); cvar_t sv_public = CVAR("sv_public", "0"); cvar_t sv_listen_qw = CVARAF("sv_listen_qw", "1", "sv_listen", 0); cvar_t sv_listen_nq = CVAR("sv_listen_nq", "0"); -cvar_t sv_listen_dp = CVAR("sv_listen_dp", "1"); +cvar_t sv_listen_dp = CVAR("sv_listen_dp", "0"); /*kinda fucked right now*/ cvar_t sv_listen_q3 = CVAR("sv_listen_q3", "0"); cvar_t sv_reportheartbeats = CVAR("sv_reportheartbeats", "1"); cvar_t sv_highchars = CVAR("sv_highchars", "1"); cvar_t sv_loadentfiles = CVAR("sv_loadentfiles", "1"); -cvar_t sv_maxrate = CVAR("sv_maxrate", "10000"); +cvar_t sv_maxrate = CVAR("sv_maxrate", "30000"); cvar_t sv_maxdrate = CVARAF("sv_maxdrate", "100000", "sv_maxdownloadrate", 0); cvar_t sv_minping = CVARF("sv_minping", "0", CVAR_SERVERINFO); @@ -162,7 +162,7 @@ cvar_t sv_port_tcp = CVARC("sv_port_tcp", "", SV_Tcpport_Callback); cvar_t sv_port_tcp6 = CVARC("sv_port_tcp6", "", SV_Tcpport6_Callback); #endif #endif -cvar_t sv_port = CVARC("sv_port", "27500", SV_Port_Callback); +cvar_t sv_port_ipv4 = CVARC("sv_port", "27500", SV_Port_Callback); #ifdef IPPROTO_IPV6 cvar_t sv_port_ipv6 = CVARC("sv_port_ipv6", "27500", SV_PortIPv6_Callback); #endif @@ -193,8 +193,8 @@ cvar_t skill = CVARF("skill", "" , CVAR_SERVERINFO); // 0, 1, 2 or 3 cvar_t spawn = CVARF("spawn", "" , CVAR_SERVERINFO); cvar_t watervis = CVARF("watervis", "" , CVAR_SERVERINFO); cvar_t rearview = CVARF("rearview", "" , CVAR_SERVERINFO); -cvar_t allow_fish = CVARF("allow_fish", "0", CVAR_SERVERINFO); cvar_t allow_luma = CVARF("allow_luma", "1", CVAR_SERVERINFO); +#pragma warningmsg("Remove this some time") cvar_t allow_bump = CVARF("allow_bump", "1", CVAR_SERVERINFO); cvar_t allow_skybox = CVARF("allow_skybox", "", CVAR_SERVERINFO); cvar_t sv_allow_splitscreen = CVARF("allow_splitscreen","",CVAR_SERVERINFO); @@ -418,6 +418,7 @@ void SV_DropClient (client_t *drop) break; case SCP_QUAKEWORLD: case SCP_NETQUAKE: + case SCP_FITZ666: case SCP_DARKPLACES6: case SCP_DARKPLACES7: MSG_WriteByte (&drop->netchan.message, svc_disconnect); @@ -454,11 +455,11 @@ void SV_DropClient (client_t *drop) drop->kills=0; drop->deaths=0; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, drop->edict); - if (pr_nqglobal_struct->SetChangeParms) + if (pr_global_ptrs->SetChangeParms) PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetChangeParms); for (j=0 ; jspawnparamglobals[j]) + rs.parm[j] = *pr_global_ptrs->spawnparamglobals[j]; Rank_SetPlayerStats(drop->rankid, &rs); } } @@ -556,8 +557,8 @@ void SV_DropClient (client_t *drop) if (drop->netchan.remote_address.type == NA_LOOPBACK) { Netchan_Transmit(&drop->netchan, 0, "", SV_RateForClient(drop)); -#ifdef _MSC_VER -#pragma message("This mans that we may not see the reason we kicked ourselves.") +#ifdef warningmsg +#pragma warningmsg("This mans that we may not see the reason we kicked ourselves.") #endif CL_Disconnect(); drop->state = cs_free; //don't do zombie stuff @@ -777,6 +778,7 @@ int SV_CalcPing (client_t *cl, qboolean forcecalc) case SCP_DARKPLACES6: case SCP_DARKPLACES7: case SCP_NETQUAKE: + case SCP_FITZ666: case SCP_QUAKEWORLD: ping = 0; count = 0; @@ -877,8 +879,8 @@ void SV_FullClientUpdate (client_t *client, sizebuf_t *buf, unsigned int ftepext MSG_WriteByte (buf, i); MSG_WriteFloat (buf, realtime - client->connection_started); -#ifdef _MSC_VER -#pragma message("this is a bug: it can be broadcast to all qw clients") +#ifdef warningmsg +#pragma warningmsg("this is a bug: it can be broadcast to all qw clients") #endif if (ftepext & PEXT_BIGUSERINFOS) Q_strncpyz (info, client->userinfo, sizeof(info)); @@ -1462,13 +1464,13 @@ void SV_GetNewSpawnParms(client_t *cl) else #endif { - if (pr_nqglobal_struct->SetNewParms) + if (pr_global_ptrs->SetNewParms) PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); } for (i=0 ; ispawn_parms[i] = *spawnparamglobals[i]; + if (pr_global_ptrs->spawnparamglobals[i]) + cl->spawn_parms[i] = *pr_global_ptrs->spawnparamglobals[i]; else cl->spawn_parms[i] = 0; } @@ -1546,6 +1548,7 @@ void VARGS SV_RejectMessage(int protocol, char *format, ...) { #ifdef NQPROT case SCP_NETQUAKE: + case SCP_FITZ666: string[4] = CCREP_REJECT; vsnprintf (string+5,sizeof(string)-1-5, format,argptr); len = strlen(string+4)+1+4; @@ -1597,14 +1600,18 @@ void SV_AcceptMessage(int protocol) { #ifdef NQPROT case SCP_NETQUAKE: - SZ_Clear(&sb); - MSG_WriteLong(&sb, 0); - MSG_WriteByte(&sb, CCREP_ACCEPT); - NET_LocalAddressForRemote(svs.sockets, &net_from, &localaddr, 0); - MSG_WriteLong(&sb, ShortSwap(localaddr.port)); - *(int*)sb.data = BigLong(NETFLAG_CTL|sb.cursize); - NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from); - return; + case SCP_FITZ666: + if (net_from.type != NA_LOOPBACK) + { + SZ_Clear(&sb); + MSG_WriteLong(&sb, 0); + MSG_WriteByte(&sb, CCREP_ACCEPT); + NET_LocalAddressForRemote(svs.sockets, &net_from, &localaddr, 0); + MSG_WriteLong(&sb, ShortSwap(localaddr.port)); + *(int*)sb.data = BigLong(NETFLAG_CTL|sb.cursize); + NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from); + return; + } case SCP_DARKPLACES6: case SCP_DARKPLACES7: strcpy(string, "accept"); @@ -1677,6 +1684,7 @@ client_t *SVC_DirectConnect(void) int challenge; int huffcrc = 0; char guid[128] = ""; + char basic[80]; qboolean redirect = false; int maxpacketentities; @@ -1925,6 +1933,7 @@ client_t *SVC_DirectConnect(void) newcl->protocol = protocol; Q_strncpyz(newcl->guid, guid, sizeof(newcl->guid)); + newcl->maxmodels = 256; if (protocol == SCP_QUAKEWORLD) //readd? { newcl->max_net_ents = 512; @@ -1932,9 +1941,15 @@ client_t *SVC_DirectConnect(void) newcl->max_net_ents += 512; if (newcl->fteprotocolextensions & PEXT_ENTITYDBL2) newcl->max_net_ents += 1024; + + if (newcl->fteprotocolextensions & PEXT_MODELDBL) + newcl->maxmodels = MAX_MODELS; } else if (ISDPCLIENT(newcl)) + { newcl->max_net_ents = 32767; + newcl->maxmodels = 1024; + } else newcl->max_net_ents = 600; @@ -2025,21 +2040,9 @@ client_t *SVC_DirectConnect(void) SV_FixupName(name, temp.namebuf, sizeof(temp.namebuf)); name = temp.namebuf; - if (!*name) - { - name = "unnamed"; - } - else if (!stricmp(name, "console")) - name = "Not Console"; //have fun dudes. - else - { - char *t = name; - //work around an ezquake bug that has been there since the beginning in one form or another. - while (*(unsigned char*)t == 0xff) - t++; - if (!*t) - name = "invisible"; - } + deleetstring(basic, name); + if (!*basic || strstr(basic, "console")) + name = "unnamed"; //have fun dudes. // count up the clients and spectators clients = 0; @@ -2835,8 +2838,16 @@ qboolean SV_ConnectionlessPacket (void) else if (!strcmp(c, "realip")) SVC_RealIP (); else if (!PR_GameCodePacket(net_message.data+4)) - Con_Printf ("bad connectionless packet from %s:\n%s\n" - , NET_AdrToString (adr, sizeof(adr), net_from), s); + { + static unsigned int lt; + unsigned int ct = Sys_Milliseconds(); + if (ct - lt > 5*1000) + { + Con_Printf ("bad connectionless packet from %s: \"%s\"\n" + , NET_AdrToString (adr, sizeof(adr), net_from), c); + lt = ct; + } + } return false; } @@ -2858,8 +2869,6 @@ void SVNQ_ConnectionlessPacket(void) if (!sv_listen_nq.value) return; - if (svs.netprim.coordsize != 2) - return; //no, start using dp7 instead. MSG_BeginReading(svs.netprim); header = LongSwap(MSG_ReadLong()); @@ -3127,6 +3136,8 @@ qboolean SV_ReadPackets (float *delay) laggedpacket_t *lp; char *banreason; qboolean received = false; + int giveup = 5000; /*we're fucked if we need this to be this high, but at least we can retain some clients if we're really running that slow*/ + int cookie = 0; for (i = 0; i < MAX_CLIENTS; i++) //fixme: shouldn't we be using svs.allocated_client_slots ? { @@ -3177,9 +3188,9 @@ qboolean SV_ReadPackets (float *delay) } #ifdef SERVER_DEMO_PLAYBACK - while (SV_GetPacket()) + while (giveup-- > 0 && SV_GetPacket()) #else - while (NET_GetPacket (NS_SERVER)) + while (giveup-- > 0 && (cookie=NET_GetPacket (NS_SERVER, cookie)) >= 0) #endif { banreason = SV_BannedReason (&net_from); @@ -3241,8 +3252,8 @@ qboolean SV_ReadPackets (float *delay) #ifdef Q3SERVER if (ISQ3CLIENT(cl)) { -#ifdef _MSC_VER -#pragma message("qwoverq3: fixme: this will block qw+q3 clients from the same ip") +#ifdef warningmsg +#pragma warningmsg("qwoverq3: fixme: this will block qw+q3 clients from the same ip") #endif if (cl->state != cs_zombie) { @@ -3405,24 +3416,37 @@ void SV_GetConsoleCommands (void) } } - +#define MINDRATE 500 +#define MINRATE 500 int SV_RateForClient(client_t *cl) { int rate; - if (cl->download && cl->drate) + if (cl->download) { rate = cl->drate; - if (rate > sv_maxdrate.value) - rate = sv_maxdrate.value; + if (sv_maxdrate.ival) + { + if (!rate || rate > sv_maxdrate.value) + rate = sv_maxdrate.value; + else if (rate < MINDRATE) + rate = MINDRATE; + } + else if (rate >= 1 && rate < MINDRATE) + rate = MINDRATE; } else { rate = cl->rate; - if (rate > sv_maxrate.value) - rate = sv_maxrate.value; + if (sv_maxrate.ival) + { + if (rate > sv_maxrate.value) + rate = sv_maxrate.value; + else if (rate < MINRATE) + rate = MINRATE; + } + else if (rate >= 1 && rate < MINRATE) + rate = MINRATE; } - if (rate < 500) - rate = 500; return rate; } @@ -3800,7 +3824,7 @@ void SV_InitLocal (void) extern cvar_t sv_wateraccelerate; extern cvar_t sv_friction; extern cvar_t sv_waterfriction; - extern cvar_t sv_sound_watersplash; + extern cvar_t sv_sound_watersplash, sv_sound_land; extern cvar_t pr_allowbutton1; extern cvar_t pm_bunnyspeedcap; @@ -3848,7 +3872,6 @@ void SV_InitLocal (void) Cvar_Register (&watervis, cvargroup_serverinfo); Cvar_Register (&rearview, cvargroup_serverinfo); Cvar_Register (&mirrors, cvargroup_serverinfo); - Cvar_Register (&allow_fish, cvargroup_serverinfo); Cvar_Register (&allow_luma, cvargroup_serverinfo); Cvar_Register (&allow_bump, cvargroup_serverinfo); Cvar_Register (&allow_skybox, cvargroup_serverinfo); @@ -3871,7 +3894,8 @@ void SV_InitLocal (void) Cvar_Register (&sv_wateraccelerate, cvargroup_serverphysics); Cvar_Register (&sv_friction, cvargroup_serverphysics); Cvar_Register (&sv_waterfriction, cvargroup_serverphysics); - Cvar_Register (&sv_sound_watersplash, cvargroup_serverphysics); + Cvar_Register (&sv_sound_watersplash, cvargroup_serverphysics); + Cvar_Register (&sv_sound_land, cvargroup_serverphysics); Cvar_Register (&sv_bigcoords, cvargroup_serverphysics); @@ -3915,8 +3939,8 @@ void SV_InitLocal (void) Cvar_Register (&sv_port_ipx, cvargroup_servercontrol); sv_port_ipx.restriction = RESTRICT_MAX; #endif - Cvar_Register (&sv_port, cvargroup_servercontrol); - sv_port.restriction = RESTRICT_MAX; + Cvar_Register (&sv_port_ipv4, cvargroup_servercontrol); + sv_port_ipv4.restriction = RESTRICT_MAX; Cvar_Register (&sv_reportheartbeats, cvargroup_servercontrol); @@ -3940,7 +3964,7 @@ void SV_InitLocal (void) Cvar_Register (&allow_download_pakcontents, cvargroup_serverpermissions); Cvar_Register (&allow_download_textures,cvargroup_serverpermissions); Cvar_Register (&allow_download_configs, cvargroup_serverpermissions); - Cvar_Register (&allow_download_pk3s, cvargroup_serverpermissions); + Cvar_Register (&allow_download_packages,cvargroup_serverpermissions); Cvar_Register (&allow_download_wads, cvargroup_serverpermissions); Cvar_Register (&allow_download_root, cvargroup_serverpermissions); Cvar_Register (&secure, cvargroup_serverpermissions); @@ -4092,7 +4116,7 @@ void SV_InitLocal (void) int port = atoi(com_argv[p+1]); if (!port) port = PORT_QWSERVER; - Cvar_SetValue(&sv_port, port); + Cvar_SetValue(&sv_port_ipv4, port); #ifdef IPPROTO_IPV6 Cvar_SetValue(&sv_port_ipv6, port); #endif @@ -4398,11 +4422,11 @@ qboolean ReloadRanking(client_t *cl, char *newname) cl->kills=0; cl->deaths=0; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, cl->edict); - if (pr_nqglobal_struct->SetChangeParms) + if (pr_global_ptrs->SetChangeParms) PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetChangeParms); for (j=0 ; jspawnparamglobals[j]) + rs.parm[j] = *pr_global_ptrs->spawnparamglobals[j]; Rank_SetPlayerStats(cl->rankid, &rs); cl->rankid = 0; } @@ -4442,7 +4466,7 @@ void SV_ExtractFromUserinfo (client_t *cl) int i; client_t *client; int dupc = 1; - char newname[80]; + char newname[80], basic[80]; val = Info_ValueForKey (cl->userinfo, "team"); Q_strncpyz (cl->team, val, sizeof(cl->teambuf)); @@ -4459,12 +4483,9 @@ void SV_ExtractFromUserinfo (client_t *cl) else newname[0] = 0; - if (!newname[0] && cl->protocol != SCP_BAD) + deleetstring(basic, newname); + if ((!basic[0] && cl->protocol != SCP_BAD) || strstr(basic, "console")) strcpy(newname, "unnamed"); - else if (!stricmp(val, "console")) - { - strcpy(newname, "Not Console"); - } // check to see if another user by the same name exists while (1) { @@ -4561,7 +4582,7 @@ void SV_ExtractFromUserinfo (client_t *cl) if (strlen(val)) cl->drate = atoi(val); else - cl->drate = 0; //0 disables the downloading check + cl->drate = cl->rate; //0 disables the downloading check val = Info_ValueForKey (cl->userinfo, "cl_playerclass"); if (val) diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 756d1f57f..88ec6b902 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -24,10 +24,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "pr_common.h" -#ifdef _MSC_VER -#pragma message("fixme, fix this up before adding to csqc") +#ifdef warningmsg +#pragma warningmsg("fixme, fix this up before adding to csqc") #endif -extern nqglobalvars_t realpr_nqglobal_struct; +extern globalptrs_t realpr_global_ptrs; /* @@ -1899,7 +1899,8 @@ void WPhys_RunEntity (world_t *w, wedict_t *ent) World_LinkEdict (w, ent, true); break; default: - SV_Error ("SV_Physics: bad movetype %i on %s", (int)ent->v->movetype, PR_GetString(w->progs, ent->v->classname)); +// SV_Error ("SV_Physics: bad movetype %i on %s", (int)ent->v->movetype, PR_GetString(w->progs, ent->v->classname)); + break; } if (movechain != w->edicts) @@ -2003,6 +2004,27 @@ void World_Physics_Frame(world_t *w) qboolean retouch; wedict_t *ent; + i = *w->g.physics_mode; + if (i == 0) + { + /*physics mode 0 = none*/ + return; + } + if (i == 1) + { + /*physics mode 1 = thinks only*/ + for (i=0 ; inum_edicts ; i++) + { + ent = (wedict_t*)EDICT_NUM(w->progs, i); + if (ent->isfree) + continue; + + WPhys_RunThink (w, ent); + } + return; + } + /*physics mode 2 = normal movetypes*/ + retouch = (w->g.force_retouch && (*w->g.force_retouch >= 1)); // @@ -2041,7 +2063,7 @@ void World_Physics_Frame(world_t *w) } if (retouch) - w->g.force_retouch-=1; + *w->g.force_retouch-=1; } /* @@ -2102,13 +2124,16 @@ qboolean SV_Physics (void) usercmd_t ucmd; static int old_bot_time; //I hate using floats for timers. + int newbottime, ms; client_t *oldhost; edict_t *oldplayer; host_frametime = (Sys_Milliseconds() - old_bot_time) / 1000.0f; if (1 || host_frametime >= 1 / 72.0f) { memset(&ucmd, 0, sizeof(ucmd)); - old_bot_time = Sys_Milliseconds(); + newbottime = Sys_Milliseconds(); + ms = newbottime - old_bot_time; + old_bot_time = newbottime; for (i = 1; i <= sv.allocated_client_slots; i++) { if (svs.clients[i-1].state && svs.clients[i-1].protocol == SCP_BAD) @@ -2116,6 +2141,7 @@ qboolean SV_Physics (void) oldhost = host_client; oldplayer = sv_player; host_client = &svs.clients[i-1]; + host_client->isindependant = true; sv_player = host_client->edict; SV_PreRunCmd(); @@ -2124,11 +2150,11 @@ qboolean SV_Physics (void) ucmd.msec = host_frametime*1000; #else // FIXME: Something very weird is going on here! - ucmd.msec = 0; + ucmd.msec = ms; #endif - ucmd.angles[0] = (int)(sv_player->v->angles[0] * (65535/360.0f)); - ucmd.angles[1] = (int)(sv_player->v->angles[1] * (65535/360.0f)); - ucmd.angles[2] = (int)(sv_player->v->angles[2] * (65535/360.0f)); + ucmd.angles[0] = (int)(sv_player->v->v_angle[0] * (65535/360.0f)); + ucmd.angles[1] = (int)(sv_player->v->v_angle[1] * (65535/360.0f)); + ucmd.angles[2] = (int)(sv_player->v->v_angle[2] * (65535/360.0f)); ucmd.forwardmove = sv_player->xv->movement[0]; ucmd.sidemove = sv_player->xv->movement[1]; ucmd.upmove = sv_player->xv->movement[2]; diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 8325c708d..4f43e1b1e 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -253,6 +253,7 @@ void SV_PrintToClient(client_t *cl, int level, char *string) case SCP_DARKPLACES6: case SCP_DARKPLACES7: case SCP_NETQUAKE: + case SCP_FITZ666: #ifdef NQPROT ClientReliableWrite_Begin (cl, svc_print, strlen(string)+3); if (level == PRINT_CHAT) @@ -578,6 +579,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int break; #ifdef NQPROT case SCP_NETQUAKE: + case SCP_FITZ666: case SCP_DARKPLACES6: case SCP_DARKPLACES7: if (reliable) @@ -711,6 +713,7 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int #ifdef NQPROT case SCP_NETQUAKE: + case SCP_FITZ666: case SCP_DARKPLACES6: case SCP_DARKPLACES7: //extra prediction stuff if (reliable) @@ -985,9 +988,9 @@ void SV_FindModelNumbers (void) { if (!sv.strings.model_precache[i]) break; - if (!strcmp(sv.strings.model_precache[i],"progs/spike.mdl")) + if (!strcmp(sv.strings.model_precache[i],"progs/spike.mdl") && sv.multicast.prim.coordsize == 2) sv_nailmodel = i; - if (!strcmp(sv.strings.model_precache[i],"progs/s_spike.mdl")) + if (!strcmp(sv.strings.model_precache[i],"progs/s_spike.mdl") && sv.multicast.prim.coordsize == 2) sv_supernailmodel = i; if (!strcmp(sv.strings.model_precache[i],"progs/player.mdl")) sv_playermodel = i; @@ -1492,7 +1495,7 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf if (!client->spectator) { statsi[STAT_ACTIVEWEAPON] = ent->v->weapon; - if (client->csqcactive) + if (client->csqcactive || client->protocol != SCP_QUAKEWORLD) statsi[STAT_WEAPONFRAME] = ent->v->weaponframe; } @@ -2121,7 +2124,7 @@ void SV_SendClientMessages (void) int i, j; client_t *c; int sentbytes, fnum; - float pt = sv.world.physicstime; + float pt = sv.paused?realtime:sv.world.physicstime; #ifdef Q3SERVER if (svs.gametype == GT_QUAKE3) @@ -2262,14 +2265,14 @@ void SV_SendClientMessages (void) if (c->state == cs_connected && !c->datagram.cursize && !c->netchan.message.cursize) { - if (c->nextservertimeupdate < sv.world.physicstime) + if (c->nextservertimeupdate < pt) { //part of the nq protocols allowed downloading content over isdn //the nop requirement of the protocol persisted to prevent timeouts when content loading is otherwise slow.. //aditionally we might need this for lost packets, not sure //but the client isn't able to respond unless we send an occasional datagram if (c->nextservertimeupdate) MSG_WriteByte(&c->datagram, svc_nop); - c->nextservertimeupdate = sv.world.physicstime+5; + c->nextservertimeupdate = pt+5; } } } diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index b80d94c41..9420b0381 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -49,12 +49,13 @@ cvar_t sv_antilag = CVARFD("sv_antilag", "1", CVAR_SERVERINFO, "Attempt to bac cvar_t sv_antilag_frac = CVARF("sv_antilag_frac", "1", CVAR_SERVERINFO); cvar_t sv_cheatpc = CVAR("sv_cheatpc", "125"); cvar_t sv_cheatspeedchecktime = CVAR("sv_cheatspeedchecktime", "30"); -cvar_t sv_playermodelchecks = CVAR("sv_playermodelchecks", "1"); +cvar_t sv_playermodelchecks = CVAR("sv_playermodelchecks", "0"); cvar_t sv_cmdlikercon = SCVAR("sv_cmdlikercon", "0"); //set to 1 to allow a password of username:password instead of the correct rcon password. cvar_t cmd_allowaccess = SCVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd to execute console commands on the server. cvar_t cmd_gamecodelevel = SCVAR("cmd_gamecodelevel", "50"); //execution level which gamecode is told about (for unrecognised commands) +cvar_t sv_pure = CVARFD("sv_pure", "", CVAR_SERVERINFO, "The most evil cvar in the world."); cvar_t sv_nomsec = CVARD("sv_nomsec", "0", "Ignore client msec times, runs using NQ physics instead."); cvar_t sv_edgefriction = CVARAF("sv_edgefriction", "2", "edgefriction", 0); @@ -377,15 +378,13 @@ void SV_New_f (void) // send server info string if (sv.demostatevalid) { - ClientReliableCheckBlock(host_client, 20 + strlen(sv.demoinfo)); - ClientReliableWrite_Byte (host_client, svc_stufftext); + ClientReliableWrite_Begin(host_client, svc_stufftext, 20 + strlen(sv.demoinfo)); ClientReliableWrite_String (host_client, va("fullserverinfo \"%s\"\n", sv.demoinfo) ); } else #endif { - ClientReliableCheckBlock(host_client, 20 + strlen(svs.info)); - ClientReliableWrite_Byte (host_client, svc_stufftext); + ClientReliableWrite_Begin(host_client, svc_stufftext, 20 + strlen(svs.info)); ClientReliableWrite_String (host_client, va("fullserverinfo \"%s\"\n", svs.info) ); } @@ -395,9 +394,7 @@ void SV_New_f (void) SV_CheckRealIP(host_client, false); // send music - ClientReliableCheckBlock(host_client, 2); - - ClientReliableWrite_Byte (host_client, svc_cdtrack); + ClientReliableWrite_Begin(host_client, svc_cdtrack, 2); if (progstype == PROG_H2) ClientReliableWrite_Byte (host_client, sv.h2cdtrack); else if (svprogfuncs) @@ -406,7 +403,26 @@ void SV_New_f (void) ClientReliableWrite_Byte (host_client, 0); SV_LogPlayer(host_client, "new (QW)"); + + + + { + char buffer[1024]; + + FS_GetPackNames(buffer, sizeof(buffer), false, true); /*retain extensions, or we'd have to assume pk3*/ + ClientReliableWrite_Begin(host_client, svc_stufftext, 1+11+strlen(buffer)+1+1); + ClientReliableWrite_SZ(host_client, "//paknames ", 11); + ClientReliableWrite_SZ(host_client, buffer, strlen(buffer)); + ClientReliableWrite_String(host_client, "\n"); + + FS_GetPackHashes(buffer, sizeof(buffer), false); + ClientReliableWrite_Begin(host_client, svc_stufftext, 1+7+strlen(buffer)+1+1); + ClientReliableWrite_SZ(host_client, "//paks ", 7); + ClientReliableWrite_SZ(host_client, buffer, strlen(buffer)); + ClientReliableWrite_String(host_client, "\n"); + } } + #define GAME_DEATHMATCH 0 #define GAME_COOP 1 void SVNQ_New_f (void) @@ -476,8 +492,30 @@ void SVNQ_New_f (void) { #ifdef NQPROT case SCP_NETQUAKE: + case SCP_FITZ666: SV_LogPlayer(host_client, "new (NQ)"); - MSG_WriteLong (&host_client->netchan.message, NQ_PROTOCOL_VERSION); + if (sv.nqdatagram.prim.anglesize != 1 || sv.nqdatagram.prim.coordsize != 2) + { + int rmqfl = + ((sv.nqdatagram.prim.coordsize==4)?RMQFL_FLOATCOORD:0) | + ((sv.nqdatagram.prim.anglesize==2)?RMQFL_SHORTANGLE:0); + host_client->protocol = SCP_FITZ666; /*mneh, close enough, the rmq stuff is just modifiers*/ + + if (rmqfl) + { + MSG_WriteLong (&host_client->netchan.message, RMQ_PROTOCOL_VERSION); + MSG_WriteLong (&host_client->netchan.message, rmqfl); + } + else + { + MSG_WriteLong (&host_client->netchan.message, FITZ_PROTOCOL_VERSION); + } + } + else + { + host_client->protocol = SCP_NETQUAKE; + MSG_WriteLong (&host_client->netchan.message, NQ_PROTOCOL_VERSION); + } MSG_WriteByte (&host_client->netchan.message, (sv.allocated_client_slots>16)?16:sv.allocated_client_slots); break; case SCP_DARKPLACES6: @@ -974,6 +1012,7 @@ void SV_Modellist_f (void) { unsigned int i; unsigned int n; + qboolean initial; if (host_client->state != cs_connected) { @@ -999,40 +1038,6 @@ void SV_Modellist_f (void) return; } - if (n == 0 && (host_client->zquake_extensions & Z_EXT_VWEP)) - { - char mname[MAX_QPATH]; - char vweaplist[1024] = "//vwep"; - //int pos = strlen(vweaplist); // warning: unused variable ‘pos’ - - for (i = 0; sv.strings.vw_model_precache[i]; i++) - { - //grab the model name... without a progs/ prefix if it has one - if (!strncmp(sv.strings.vw_model_precache[i], "progs/", 6)) - Q_strncpy(mname, sv.strings.vw_model_precache[i]+6, sizeof(mname)); - else - Q_strncpy(mname, sv.strings.vw_model_precache[i], sizeof(mname)); - - //strip .mdl extensions - if (!strcmp(COM_FileExtension(mname), "mdl")) - COM_StripExtension(mname, mname, sizeof(mname)); - - //add it to the vweap command, taking care of any remaining spaces in names. - if (strchr(mname, ' ')) - Q_strncatz(vweaplist, va(" \"%s\"", mname), sizeof(vweaplist)); - else - Q_strncatz(vweaplist, va(" %s", mname), sizeof(vweaplist)); - } - - if (strlen(vweaplist) <= sizeof(vweaplist)-2) - { - Q_strncatz(vweaplist, "\n", sizeof(vweaplist)); - - ClientReliableWrite_Begin(host_client, svc_stufftext, 2+strlen(vweaplist)); - ClientReliableWrite_String(host_client, vweaplist); - } - } - //NOTE: This doesn't go through ClientReliableWrite since it's before the user //spawns. These functions are written to not overflow if (host_client->num_backbuf) @@ -1044,6 +1049,8 @@ void SV_Modellist_f (void) return; } + initial = (n==0); + #ifdef PEXT_MODELDBL if (n > 255) { @@ -1057,12 +1064,6 @@ void SV_Modellist_f (void) MSG_WriteByte (&host_client->netchan.message, n); } - host_client->maxmodels = 256; -#ifdef PEXT_MODELDBL - if (host_client->fteprotocolextensions & PEXT_MODELDBL) - host_client->maxmodels = MAX_MODELS; -#endif - #ifdef SERVER_DEMO_PLAYBACK if (sv.democausesreconnect) //read the list from somewhere else { @@ -1096,6 +1097,41 @@ void SV_Modellist_f (void) // next msg MSG_WriteByte (&host_client->netchan.message, n & 0xff); + + + if (initial && (host_client->zquake_extensions & Z_EXT_VWEP)) + { + char mname[MAX_QPATH]; + char vweaplist[1024] = "//vwep"; + //int pos = strlen(vweaplist); // warning: unused variable ‘pos’ + + for (i = 0; sv.strings.vw_model_precache[i]; i++) + { + //grab the model name... without a progs/ prefix if it has one + if (!strncmp(sv.strings.vw_model_precache[i], "progs/", 6)) + Q_strncpy(mname, sv.strings.vw_model_precache[i]+6, sizeof(mname)); + else + Q_strncpy(mname, sv.strings.vw_model_precache[i], sizeof(mname)); + + //strip .mdl extensions + if (!strcmp(COM_FileExtension(mname), "mdl")) + COM_StripExtension(mname, mname, sizeof(mname)); + + //add it to the vweap command, taking care of any remaining spaces in names. + if (strchr(mname, ' ')) + Q_strncatz(vweaplist, va(" \"%s\"", mname), sizeof(vweaplist)); + else + Q_strncatz(vweaplist, va(" %s", mname), sizeof(vweaplist)); + } + + if (strlen(vweaplist) <= sizeof(vweaplist)-2) + { + Q_strncatz(vweaplist, "\n", sizeof(vweaplist)); + + ClientReliableWrite_Begin(host_client, svc_stufftext, 2+strlen(vweaplist)); + ClientReliableWrite_String(host_client, vweaplist); + } + } } /* @@ -1103,7 +1139,7 @@ void SV_Modellist_f (void) SV_PreSpawn_f ================== */ -void SV_PreSpawn_f (void) +void SVQW_PreSpawn_f (void) { unsigned buf, bufs; unsigned check; @@ -1262,6 +1298,10 @@ void SV_PreSpawn_f (void) MSG_WriteAngle(&host_client->netchan.message, 0); } } + else if (state->number >= host_client->max_net_ents || state->modelindex >= host_client->maxmodels) + { + /*can't send this ent*/ + } else if (host_client->fteprotocolextensions & PEXT_SPAWNSTATIC2) { MSG_WriteByte(&host_client->netchan.message, svcfte_spawnbaseline2); @@ -1594,8 +1634,8 @@ void SV_Begin_Core(client_t *split) // copy spawn parms out of the client_t for (i=0 ; i< NUM_SPAWN_PARMS ; i++) { - if (spawnparamglobals[i]) - *spawnparamglobals[i] = split->spawn_parms[i]; + if (pr_global_ptrs->spawnparamglobals[i]) + *pr_global_ptrs->spawnparamglobals[i] = split->spawn_parms[i]; } // call the spawn function @@ -1625,8 +1665,8 @@ void SV_Begin_Core(client_t *split) eval2->_float = 1; for (j=0 ; j< NUM_SPAWN_PARMS ; j++) { - if (spawnparamglobals[j]) - *spawnparamglobals[j] = split->spawn_parms[j]; + if (pr_global_ptrs->spawnparamglobals[j]) + *pr_global_ptrs->spawnparamglobals[j] = split->spawn_parms[j]; } pr_global_struct->time = sv.world.physicstime; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); @@ -1638,8 +1678,8 @@ void SV_Begin_Core(client_t *split) // copy spawn parms out of the client_t for (i=0 ; i< NUM_SPAWN_PARMS ; i++) { - if (spawnparamglobals[i]) - *spawnparamglobals[i] = split->spawn_parms[i]; + if (pr_global_ptrs->spawnparamglobals[i]) + *pr_global_ptrs->spawnparamglobals[i] = split->spawn_parms[i]; } // call the spawn function @@ -2411,7 +2451,7 @@ qboolean SV_AllowDownload (const char *name) extern cvar_t allow_download_demos; extern cvar_t allow_download_maps; extern cvar_t allow_download_textures; - extern cvar_t allow_download_pk3s; + extern cvar_t allow_download_packages; extern cvar_t allow_download_wads; extern cvar_t allow_download_root; extern cvar_t allow_download_configs; @@ -2430,6 +2470,17 @@ qboolean SV_AllowDownload (const char *name) if (strchr(name, '\\')) //no windows paths - grow up lame windows users. return false; + if (!strncmp(name, "package/", 8)) + { + if (!strcmp("pk4", COM_FileExtension(name)) || !strcmp("pk3", COM_FileExtension(name)) || !strcmp("pak", COM_FileExtension(name))) + { + /*do not permit 'id1/pak1.pak' or 'baseq3/pak0.pk3' or any similarly named packages. such packages would violate copyright, and must be obtained through other means (like buying the damn game)*/ + //if (!strstr(name, "/pak")) + return !!allow_download_packages.value; + } + return false; + } + if (strncmp(name, "maps/", 5) == 0) return !!allow_download_maps.value; @@ -2457,10 +2508,10 @@ qboolean SV_AllowDownload (const char *name) if (!strcmp("wad", COM_FileExtension(name))) return !!allow_download_wads.value; - //pk3s. - if (!strcmp("pk3", COM_FileExtension(name)) || !strcmp("pak", COM_FileExtension(name))) + //pak/pk3s. + if (!strcmp("pk4", COM_FileExtension(name)) || !strcmp("pk3", COM_FileExtension(name)) || !strcmp("pak", COM_FileExtension(name))) if (strnicmp(name, "pak", 3)) //don't give out q3 pk3 files. - return !!allow_download_pk3s.value; + return !!allow_download_packages.value; if (!strcmp("cfg", COM_FileExtension(name))) return !!allow_download_configs.value; @@ -2494,6 +2545,8 @@ static int SV_LocateDownload(char *name, flocation_t *loc, char **replacementnam *p = (char)tolower(*p); } + + if (!SV_AllowDownload(name)) return -2; //not permitted (even if it exists). @@ -2519,7 +2572,19 @@ static int SV_LocateDownload(char *name, flocation_t *loc, char **replacementnam if (!strncmp(name, "demos/", 6)) name = va("%s/%s", sv_demoDir.string, name+6); - found = FS_FLocateFile(name, FSLFRT_IFFOUND, loc); + if (!strncmp(name, "package/", 8)) + { + vfsfile_t *f; + f = FS_OpenVFS(name+8, "rb", FS_ROOT); + if (f) + { + VFS_CLOSE(f); + return -5; //found package + } + return -1; //not found + } + else + found = FS_FLocateFile(name, FSLFRT_IFFOUND, loc); //nexuiz names certain files as .wav but they're really .ogg on disk. if (!found && replacementname) @@ -2604,23 +2669,24 @@ void SV_DownloadSize_f(void) switch(SV_LocateDownload(name, &loc, &redirected, true)) { - case -4: + case -4: /*redirect*/ name = va("dlsize \"%s\" r \"%s\"\n", name, redirected); ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name)); ClientReliableWrite_String (host_client, name); break; default: - case -1: + case -1: /*not found*/ name = va("dlsize \"%s\" e\n", name); ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name)); ClientReliableWrite_String (host_client, name); break; - case -2: + case -2: /*permission*/ name = va("dlsize \"%s\" p\n", name); ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name)); ClientReliableWrite_String (host_client, name); break; - case 0: + case -5: /*package*/ + case 0: /*exists*/ name = va("dlsize \"%s\" %u\n", name, loc.len); ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name)); ClientReliableWrite_String (host_client, name); @@ -2648,26 +2714,36 @@ void SV_BeginDownload_f(void) return; } - result = SV_LocateDownload(name, &loc, &redirection, false); - *host_client->downloadfn = 0; + if (host_client->download) { VFS_CLOSE (host_client->download); host_client->download = NULL; } - //redirection protocol-specific code goes here. - if (result == -4) + result = SV_LocateDownload(name, &loc, &redirection, false); + + if (result == -5) { + result = 0; + host_client->download = FS_OpenVFS(name+8, "rb", FS_ROOT); + } + else + { + //redirection protocol-specific code goes here. + if (result == -4) + { + } + + if (result == 0) + { //if we are allowed and could find it + host_client->download = FS_OpenReadLocation(&loc); + } } - if (result == 0) - { //if we are allowed and could find it - host_client->download = FS_OpenReadLocation(&loc); - if (!host_client->download) - result = -1; //this isn't likely, but hey. - } + if (!host_client->download) + result = -1; //this isn't likely, but hey. //handle errors if (result != 0) @@ -3353,7 +3429,8 @@ void SV_Rate_f (void) return; } - host_client->rate = atoi(Cmd_Argv(1)); + Info_SetValueForKey (host_client->userinfo, "rate", Cmd_Argv(1), sizeof(host_client->userinfo)); + SV_ExtractFromUserinfo (host_client); SV_ClientTPrintf (host_client, PRINT_HIGH, STL_RATESETTO, SV_RateForClient(host_client)); } @@ -4003,12 +4080,12 @@ void Cmd_Join_f (void) // FIXME, bump the client's userid? // call the progs to get default spawn parms for the new client - if (pr_nqglobal_struct->SetNewParms) + if (pr_global_ptrs->SetNewParms) PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); for (i=0 ; ispawn_parms[i] = *spawnparamglobals[i]; + if (pr_global_ptrs->spawnparamglobals[i]) + host_client->spawn_parms[i] = *pr_global_ptrs->spawnparamglobals[i]; else host_client->spawn_parms[i] = 0; } @@ -4095,12 +4172,12 @@ void Cmd_Observe_f (void) // FIXME, bump the client's userid? // call the progs to get default spawn parms for the new client - if (pr_nqglobal_struct->SetNewParms) + if (pr_global_ptrs->SetNewParms) PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); for (i=0 ; ispawn_parms[i] = *spawnparamglobals[i]; + if (pr_global_ptrs->spawnparamglobals[i]) + host_client->spawn_parms[i] = *pr_global_ptrs->spawnparamglobals[i]; else host_client->spawn_parms[i] = 0; } @@ -4333,8 +4410,8 @@ void SVNQ_Begin_f (void) // copy spawn parms out of the client_t for (i=0 ; i< NUM_SPAWN_PARMS ; i++) { - if (spawnparamglobals[i]) - *spawnparamglobals[i] = host_client->spawn_parms[i]; + if (pr_global_ptrs->spawnparamglobals[i]) + *pr_global_ptrs->spawnparamglobals[i] = host_client->spawn_parms[i]; } // call the spawn function @@ -4348,8 +4425,8 @@ void SVNQ_Begin_f (void) // copy spawn parms out of the client_t for (i=0 ; i< NUM_SPAWN_PARMS ; i++) { - if (spawnparamglobals[i]) - *spawnparamglobals[i] = host_client->spawn_parms[i]; + if (pr_global_ptrs->spawnparamglobals[i]) + *pr_global_ptrs->spawnparamglobals[i] = host_client->spawn_parms[i]; } // call the spawn function @@ -4423,76 +4500,110 @@ void SVNQ_PreSpawn_f (void) edict_t *ent; entity_state_t *state; int i, e; + int buf = atoi(Cmd_Argv(1)); + int st; if (host_client->state != cs_connected) { Con_Printf ("prespawn not valid -- already spawned\n"); return; } - for (e = 1; e < sv.world.num_edicts && e < host_client->max_net_ents; e++) + st = 0; + if (buf >= st) { - ent = EDICT_NUM(svprogfuncs, e); - state = &ent->baseline; - - if (!state->number || !state->modelindex) - { //ent doesn't have a baseline - continue; - } - - if (!ent) + while (host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)) //baselines { - MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline); - - MSG_WriteShort (&host_client->netchan.message, e); - - MSG_WriteByte (&host_client->netchan.message, 0); - - MSG_WriteByte (&host_client->netchan.message, 0); - MSG_WriteByte (&host_client->netchan.message, 0); - MSG_WriteByte (&host_client->netchan.message, 0); - for (i=0 ; i<3 ; i++) + e = buf-st; + if (e >= sv.world.num_edicts) { - MSG_WriteCoord(&host_client->netchan.message, 0); - MSG_WriteAngle(&host_client->netchan.message, 0); + if (e < sv.world.max_edicts) + buf += sv.world.max_edicts - sv.world.num_edicts; + break; } - } - else - { - if (ISDPCLIENT(host_client) && (state->modelindex > 255 || state->frame > 255)) - { - MSG_WriteByte(&host_client->netchan.message, svcdp_spawnbaseline2); + buf++; - MSG_WriteShort (&host_client->netchan.message, e); + ent = EDICT_NUM(svprogfuncs, e); + state = &ent->baseline; - MSG_WriteShort (&host_client->netchan.message, state->modelindex); - MSG_WriteShort (&host_client->netchan.message, state->frame); + if (!state->number || !state->modelindex) + { //ent doesn't have a baseline + continue; } - else + + if (!ent) { MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline); MSG_WriteShort (&host_client->netchan.message, e); - MSG_WriteByte (&host_client->netchan.message, state->modelindex&255); - MSG_WriteByte (&host_client->netchan.message, state->frame&255); - } + MSG_WriteByte (&host_client->netchan.message, 0); - MSG_WriteByte (&host_client->netchan.message, (int)state->colormap); - MSG_WriteByte (&host_client->netchan.message, (int)state->skinnum); - for (i=0 ; i<3 ; i++) + MSG_WriteByte (&host_client->netchan.message, 0); + MSG_WriteByte (&host_client->netchan.message, 0); + MSG_WriteByte (&host_client->netchan.message, 0); + for (i=0 ; i<3 ; i++) + { + MSG_WriteCoord(&host_client->netchan.message, 0); + MSG_WriteAngle(&host_client->netchan.message, 0); + } + } + else { - MSG_WriteCoord(&host_client->netchan.message, state->origin[i]); - MSG_WriteAngle(&host_client->netchan.message, state->angles[i]); + if (ISDPCLIENT(host_client) && (state->modelindex > 255 || state->frame > 255)) + { + MSG_WriteByte(&host_client->netchan.message, svcdp_spawnbaseline2); + + MSG_WriteShort (&host_client->netchan.message, e); + + MSG_WriteShort (&host_client->netchan.message, state->modelindex); + MSG_WriteShort (&host_client->netchan.message, state->frame); + } + else + { + MSG_WriteByte(&host_client->netchan.message, svc_spawnbaseline); + + MSG_WriteShort (&host_client->netchan.message, e); + + MSG_WriteByte (&host_client->netchan.message, state->modelindex&255); + MSG_WriteByte (&host_client->netchan.message, state->frame&255); + } + + MSG_WriteByte (&host_client->netchan.message, (int)state->colormap); + MSG_WriteByte (&host_client->netchan.message, (int)state->skinnum); + for (i=0 ; i<3 ; i++) + { + MSG_WriteCoord(&host_client->netchan.message, state->origin[i]); + MSG_WriteAngle(&host_client->netchan.message, state->angles[i]); + } } } } + st += sv.world.max_edicts; - for (i = 0; i < sv.num_signon_buffers; i++) - SZ_Write (&host_client->netchan.message, sv.signon_buffers[i], sv.signon_buffer_size[i]); - - MSG_WriteByte (&host_client->netchan.message, svc_signonnum); - MSG_WriteByte (&host_client->netchan.message, 2); + if (buf >= st) + { + while (host_client->netchan.message.cursize < (host_client->netchan.message.maxsize/2)) + { + i = buf-st; + if (i >= sv.num_signon_buffers) + break; + buf++; + SZ_Write (&host_client->netchan.message, sv.signon_buffers[i], sv.signon_buffer_size[i]); + } + } + st += sv.num_signon_buffers; + if (st == buf) + { + MSG_WriteByte (&host_client->netchan.message, svc_signonnum); + MSG_WriteByte (&host_client->netchan.message, 2); + } + else + { + char *s = va("cmd prespawn %i\n", buf); + ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(s)); + ClientReliableWrite_String (host_client, s); + } host_client->send_message = true; } @@ -4674,7 +4785,7 @@ ucmd_t ucmds[] = {"pk3list", SV_PK3List_f, true}, {"modellist", SV_Modellist_f, true}, {"soundlist", SV_Soundlist_f, true}, - {"prespawn", SV_PreSpawn_f, true}, + {"prespawn", SVQW_PreSpawn_f, true}, {"spawn", SV_Spawn_f, true}, {"begin", SV_Begin_f, true}, @@ -4778,7 +4889,7 @@ ucmd_t nqucmds[] = {"god", Cmd_God_f}, {"give", Cmd_Give_f}, {"notarget", Cmd_Notarget_f}, - {"fly", NULL}, + {"fly", Cmd_Fly_f}, {"noclip", Cmd_Noclip_f}, {"pings", SV_Pings_f}, @@ -4798,10 +4909,11 @@ ucmd_t nqucmds[] = {"ban", NULL}, {"vote", SV_Vote_f}, + {"dlsize", SV_DownloadSize_f}, {"download", SV_BeginDownload_f}, {"sv_startdownload", SVDP_StartDownload_f}, - {"setinfo", SV_SetInfo_f}, + {"setinfo", SV_SetInfo_f}, {"playermodel", NULL}, {"playerskin", NULL}, {"rate", SV_Rate_f}, @@ -4810,13 +4922,14 @@ ucmd_t nqucmds[] = {"topten", Rank_ListTop10_f}, #endif - {"pext", SV_Pext_f}, - + {"pext", SV_Pext_f}, + {"enablecsqc", SV_EnableClientsCSQC}, + {"disablecsqc", SV_DisableClientsCSQC}, #ifdef VOICECHAT - {"voicetarg", SV_Voice_Target_f}, - {"vignore", SV_Voice_Ignore_f}, /*ignore/mute specific player*/ - {"muteall", SV_Voice_MuteAll_f}, /*disables*/ - {"unmuteall", SV_Voice_UnmuteAll_f}, /*reenables*/ + {"voicetarg", SV_Voice_Target_f}, + {"vignore", SV_Voice_Ignore_f}, /*ignore/mute specific player*/ + {"muteall", SV_Voice_MuteAll_f}, /*disables*/ + {"unmuteall", SV_Voice_UnmuteAll_f}, /*reenables*/ #endif {NULL, NULL} @@ -5418,7 +5531,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) sv_player->v->button0 = ucmd->buttons & 1; sv_player->v->button2 = (ucmd->buttons >> 1) & 1; - if (pr_allowbutton1.value) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows. + if (pr_allowbutton1.ival) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows. sv_player->v->button1 = ((ucmd->buttons >> 2) & 1); // DP_INPUTBUTTONS sv_player->xv->button3 = ((ucmd->buttons >> 2) & 1); @@ -5843,10 +5956,18 @@ void SV_ReadQCRequest(void) } done: + args[i] = 0; rname = MSG_ReadString(); - f = PR_FindFunction(svprogfuncs, va("Cmd_%s_%s", rname, args), PR_ANY); + if (i) + rname = va("Cmd_%s_%s", rname, args); + else + rname = va("Cmd_%s", rname); + f = PR_FindFunction(svprogfuncs, rname, PR_ANY); if (f) + { + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); PR_ExecuteProgram(svprogfuncs, f); + } else SV_ClientPrintf(host_client, PRINT_HIGH, "qcrequest \"%s\" not supported\n", rname); } @@ -5916,8 +6037,8 @@ void SV_ExecuteClientMessage (client_t *cl) if (temp1.ival) frame = &cl->frameunion.frames[(cl->netchan.incoming_acknowledged+temp1.ival) & UPDATE_MASK]; */ -#ifdef _MSC_VER -#pragma message("FIXME: make antilag optionally support non-player ents too") +#ifdef warningmsg +#pragma warningmsg("FIXME: make antilag optionally support non-player ents too") #endif for (i = 0; i < sv.allocated_client_slots; i++) { @@ -6082,7 +6203,7 @@ haveannothergo: sv_player->v->button0 = newcmd.buttons & 1; sv_player->v->button2 = (newcmd.buttons >> 1) & 1; - if (pr_allowbutton1.value) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows. + if (pr_allowbutton1.ival) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows. sv_player->v->button1 = ((newcmd.buttons >> 2) & 1); // DP_INPUTBUTTONS sv_player->xv->button3 = ((newcmd.buttons >> 2) & 1); @@ -6453,7 +6574,7 @@ void SVNQ_ReadClientMove (usercmd_t *move) host_client->edict->v->button0 = bits & 1; host_client->edict->v->button2 = (bits >> 1) & 1; - if (pr_allowbutton1.value) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows. + if (pr_allowbutton1.ival) //many mods use button1 - it's just a wasted field to many mods. So only work it if the cvar allows. host_client->edict->v->button1 = ((bits >> 2) & 1); // DP_INPUTBUTTONS host_client->edict->xv->button3 = ((bits >> 2) & 1); @@ -6532,9 +6653,9 @@ void SVNQ_ExecuteClientMessage (client_t *cl) case clc_nop: break; - case clc_delta: - cl->delta_sequence = MSG_ReadByte (); - break; +// case clc_delta: +// cl->delta_sequence = MSG_ReadByte (); +// break; case clc_move: SVNQ_ReadClientMove (&host_client->lastcmd); @@ -6550,11 +6671,11 @@ void SVNQ_ExecuteClientMessage (client_t *cl) sv_player = cl->edict; break; - case 50: - MSG_ReadLong(); + case clcdp_ackframe: + cl->delta_sequence = MSG_ReadLong(); break; case clcdp_ackdownloaddata: - SV_DarkPlacesDownloadAck(host_client); + SV_DarkPlacesDownloadAck(cl); break; #ifdef VOICECHAT @@ -6601,6 +6722,7 @@ void SV_UserInit (void) Cvar_Register (&sv_pushplayers, cvargroup_servercontrol); + Cvar_Register (&sv_pure, cvargroup_servercontrol); Cvar_Register (&sv_floodprotect, cvargroup_servercontrol); Cvar_Register (&sv_floodprotect_interval, cvargroup_servercontrol); Cvar_Register (&sv_floodprotect_messages, cvargroup_servercontrol); diff --git a/engine/server/svhl_phys.c b/engine/server/svhl_phys.c index 29476c457..ad363f74d 100644 --- a/engine/server/svhl_phys.c +++ b/engine/server/svhl_phys.c @@ -1112,10 +1112,7 @@ void SVHL_Physics_Step (hledict_t *ent) { if (hitsound) { - if (progstype == PROG_H2) - SVHL_StartSound (ent, 0, "fx/thngland.wav", 255, 1); - else - SVHL_StartSound (ent, 0, "demon/dland2.wav", 255, 1); + SVHL_StartSound (ent, 0, "demon/dland2.wav", 255, 1); } } } diff --git a/engine/server/svmodel.c b/engine/server/svmodel.c index 1347d1af6..ac73b4a4c 100644 --- a/engine/server/svmodel.c +++ b/engine/server/svmodel.c @@ -45,6 +45,7 @@ texture_t r_notexture_mip_real; texture_t *r_notexture_mip = &r_notexture_mip_real; cvar_t sv_nogetlight = SCVAR("sv_nogetlight", "0"); +cvar_t dpcompat_psa_ungroup = SCVAR ("dpcompat_psa_ungroup", "0"); unsigned *model_checksum; @@ -199,6 +200,7 @@ void Mod_Init (void) { memset (mod_novis, 0xff, sizeof(mod_novis)); Cvar_Register(&sv_nogetlight, "Memory preservation"); + Cvar_Register (&dpcompat_psa_ungroup, "Darkplaces compatibility"); } /* @@ -873,28 +875,34 @@ qboolean Mod_LoadSubmodels (lump_t *l) Mod_LoadEdges ================= */ -qboolean Mod_LoadEdges (lump_t *l) +qboolean Mod_LoadEdges (lump_t *l, qboolean lm) { - dedge_t *in; medge_t *out; int i, count; - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) + if (lm) { - Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - return false; +#pragma warningmsg("bsp2 todo") } - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname); - - loadmodel->edges = out; - loadmodel->numedges = count; - - for ( i=0 ; iv[0] = (unsigned short)LittleShort(in->v[0]); - out->v[1] = (unsigned short)LittleShort(in->v[1]); + dsedge_t *in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + { + Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname); + + loadmodel->edges = out; + loadmodel->numedges = count; + + for ( i=0 ; iv[0] = (unsigned short)LittleShort(in->v[0]); + out->v[1] = (unsigned short)LittleShort(in->v[1]); + } } return true; } @@ -1028,20 +1036,28 @@ void CalcSurfaceExtents (msurface_t *s); Mod_LoadFaces ================= */ -qboolean Mod_LoadFaces (lump_t *l) +qboolean Mod_LoadFaces (lump_t *l, qboolean lm) { - dface_t *in; + dsface_t *in; msurface_t *out; int i, count, surfnum; int planenum, side; - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) + if (lm) { - Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - return false; + in = NULL; +#pragma warningmsg("bsp2 fixme") + } + else + { + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + { + Con_Printf ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*in); } - count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->surfaces = out; @@ -1049,8 +1065,15 @@ qboolean Mod_LoadFaces (lump_t *l) for ( surfnum=0 ; surfnumfirstedge = LittleLong(in->firstedge); - out->numedges = LittleShort(in->numedges); + if (lm) + { +#pragma warningmsg("bsp2 fixme") + } + else + { + out->firstedge = LittleLong(in->firstedge); + out->numedges = LittleShort(in->numedges); + } out->flags = 0; planenum = LittleShort(in->planenum); @@ -1119,48 +1142,54 @@ void Mod_SetParent (mnode_t *node, mnode_t *parent) Mod_LoadNodes ================= */ -qboolean Mod_LoadNodes (lump_t *l) +qboolean Mod_LoadNodes (lump_t *l, qboolean lm) { int i, j, count, p; - dnode_t *in; + dsnode_t *in; mnode_t *out; - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) + if (lm) { - Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); - return false; +#pragma warningmsg("bsp2 fixme") } - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - loadmodel->nodes = out; - loadmodel->numnodes = count; - - for ( i=0 ; ifileofs); + if (l->filelen % sizeof(*in)) { - out->minmaxs[j] = LittleShort (in->mins[j]); - out->minmaxs[3+j] = LittleShort (in->maxs[j]); + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; } + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); - p = LittleLong(in->planenum); - out->plane = loadmodel->planes + p; + loadmodel->nodes = out; + loadmodel->numnodes = count; - out->firstsurface = LittleShort (in->firstface); - out->numsurfaces = LittleShort (in->numfaces); - - for (j=0 ; j<2 ; j++) + for ( i=0 ; ichildren[j]); - if (p >= 0) - out->children[j] = loadmodel->nodes + p; - else - out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); + for (j=0 ; j<3 ; j++) + { + out->minmaxs[j] = LittleShort (in->mins[j]); + out->minmaxs[3+j] = LittleShort (in->maxs[j]); + } + + p = LittleLong(in->planenum); + out->plane = loadmodel->planes + p; + + out->firstsurface = LittleShort (in->firstface); + out->numsurfaces = LittleShort (in->numfaces); + + for (j=0 ; j<2 ; j++) + { + p = LittleShort (in->children[j]); + if (p >= 0) + out->children[j] = loadmodel->nodes + p; + else + out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); + } } } - Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs return true; @@ -1171,47 +1200,54 @@ qboolean Mod_LoadNodes (lump_t *l) Mod_LoadLeafs ================= */ -qboolean Mod_LoadLeafs (lump_t *l) +qboolean Mod_LoadLeafs (lump_t *l, qboolean lm) { - dleaf_t *in; + dsleaf_t *in; mleaf_t *out; int i, j, count, p; - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) + if (lm) { - Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); - return false; +#pragma warningmsg("bsp2 fixme") } - count = l->filelen / sizeof(*in); - out = Hunk_AllocName ( count*sizeof(*out), loadname); - - loadmodel->leafs = out; - loadmodel->numleafs = count; - - for ( i=0 ; ifileofs); + if (l->filelen % sizeof(*in)) { - out->minmaxs[j] = LittleShort (in->mins[j]); - out->minmaxs[3+j] = LittleShort (in->maxs[j]); + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; } + count = l->filelen / sizeof(*in); + out = Hunk_AllocName ( count*sizeof(*out), loadname); - p = LittleLong(in->contents); - out->contents = p; + loadmodel->leafs = out; + loadmodel->numleafs = count; - out->firstmarksurface = loadmodel->marksurfaces + - (unsigned short)LittleShort(in->firstmarksurface); - out->nummarksurfaces = (unsigned short)LittleShort(in->nummarksurfaces); + for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); + out->minmaxs[3+j] = LittleShort (in->maxs[j]); + } - p = LittleLong(in->visofs); - if (p == -1) - out->compressed_vis = NULL; - else - out->compressed_vis = loadmodel->visdata + p; + p = LittleLong(in->contents); + out->contents = p; - for (j=0 ; j<4 ; j++) - out->ambient_sound_level[j] = in->ambient_level[j]; + out->firstmarksurface = loadmodel->marksurfaces + + (unsigned short)LittleShort(in->firstmarksurface); + out->nummarksurfaces = (unsigned short)LittleShort(in->nummarksurfaces); + + p = LittleLong(in->visofs); + if (p == -1) + out->compressed_vis = NULL; + else + out->compressed_vis = loadmodel->visdata + p; + + for (j=0 ; j<4 ; j++) + out->ambient_sound_level[j] = in->ambient_level[j]; + } } return true; @@ -1222,26 +1258,110 @@ qboolean Mod_LoadLeafs (lump_t *l) Mod_LoadClipnodes ================= */ -qboolean Mod_LoadClipnodes (lump_t *l) +qboolean Mod_LoadClipnodes (lump_t *l, qboolean lm) { - dclipnode_t *in; + dsclipnode_t *in; mclipnode_t *out; int i, count; hull_t *hull; - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) + if (lm) { - Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); - return false; +#pragma warningmsg("bsp2 fixme") + in = NULL; + } + else + { + in = (void *)(mod_base + l->fileofs); + if (l->filelen % sizeof(*in)) + { + Con_Printf (CON_ERROR "MOD_LoadBmodel: funny lump size in %s\n",loadmodel->name); + return false; + } + count = l->filelen / sizeof(*in); } - count = l->filelen / sizeof(*in); out = Hunk_AllocName ( count*sizeof(*out), loadname); loadmodel->clipnodes = out; loadmodel->numclipnodes = count; - if (loadmodel->fromgame == fg_halflife) + if (hexen2map) + { //hexen2. + hexen2map=false; + hull = &loadmodel->hulls[1]; + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + hull->clip_mins[0] = -16; + hull->clip_mins[1] = -16; + hull->clip_mins[2] = -24; + hull->clip_maxs[0] = 16; + hull->clip_maxs[1] = 16; + hull->clip_maxs[2] = 32; + hull->available = true; + + hull = &loadmodel->hulls[2]; + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + hull->clip_mins[0] = -24; + hull->clip_mins[1] = -24; + hull->clip_mins[2] = -20; + hull->clip_maxs[0] = 24; + hull->clip_maxs[1] = 24; + hull->clip_maxs[2] = 20; + hull->available = true; + + hull = &loadmodel->hulls[3]; + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + hull->clip_mins[0] = -16; + hull->clip_mins[1] = -16; + hull->clip_mins[2] = -12; + hull->clip_maxs[0] = 16; + hull->clip_maxs[1] = 16; + hull->clip_maxs[2] = 16; + hull->available = true; + + /* + There is some mission-pack weirdness here + in the missionpack, hull 4 is meant to be '-8 -8 -8' '8 8 8' + in the original game, hull 4 is '-40 -40 -42' '40 40 42' + */ + hull = &loadmodel->hulls[4]; + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + hull->clip_mins[0] = -8; + hull->clip_mins[1] = -8; + hull->clip_mins[2] = -8; + hull->clip_maxs[0] = 8; + hull->clip_maxs[1] = 8; + hull->clip_maxs[2] = 8; + hull->available = true; + + hull = &loadmodel->hulls[5]; + hull->clipnodes = out; + hull->firstclipnode = 0; + hull->lastclipnode = count-1; + hull->planes = loadmodel->planes; + hull->clip_mins[0] = -48; + hull->clip_mins[1] = -48; + hull->clip_mins[2] = -50; + hull->clip_maxs[0] = 48; + hull->clip_maxs[1] = 48; + hull->clip_maxs[2] = 50; + hull->available = true; + + //6 isn't used. + //7 isn't used. + } + else if (loadmodel->fromgame == fg_halflife) { hull = &loadmodel->hulls[1]; hull->clipnodes = out; @@ -1324,11 +1444,18 @@ qboolean Mod_LoadClipnodes (lump_t *l) hull->available = false; } - for (i=0 ; iplanenum = LittleLong(in->planenum); - out->children[0] = LittleShort(in->children[0]); - out->children[1] = LittleShort(in->children[1]); +#pragma warningmsg("bsp2 fixme") + } + else + { + for (i=0 ; iplanenum = LittleLong(in->planenum); + out->children[0] = LittleShort(in->children[0]); + out->children[1] = LittleShort(in->children[1]); + } } return true; @@ -1486,6 +1613,7 @@ qboolean Mod_LoadBrushModel (model_t *mod, void *buffer) unsigned int chksum; int start; qboolean noerrors; + qboolean longm = false; start = Hunk_LowMark(); @@ -1496,7 +1624,12 @@ qboolean Mod_LoadBrushModel (model_t *mod, void *buffer) i = LittleLong (header->version); - if (i == BSPVERSION || i == BSPVERSIONPREREL) + if (i == BSPVERSION_LONG) + { + loadmodel->fromgame = fg_quake; + longm = true; + } + else if (i == BSPVERSION || i == BSPVERSIONPREREL) loadmodel->fromgame = fg_quake; else if (i == BSPVERSIONHL) loadmodel->fromgame = fg_halflife; @@ -1541,7 +1674,7 @@ qboolean Mod_LoadBrushModel (model_t *mod, void *buffer) if (!sv_nogetlight.value) { noerrors = noerrors && Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]); - noerrors = noerrors && Mod_LoadEdges (&header->lumps[LUMP_EDGES]); + noerrors = noerrors && Mod_LoadEdges (&header->lumps[LUMP_EDGES], longm); noerrors = noerrors && Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); ///*/on server?*/ Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]); noerrors = noerrors && Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]); @@ -1551,14 +1684,14 @@ qboolean Mod_LoadBrushModel (model_t *mod, void *buffer) if (!sv_nogetlight.value) { noerrors = noerrors && Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); - noerrors = noerrors && Mod_LoadFaces (&header->lumps[LUMP_FACES]); + noerrors = noerrors && Mod_LoadFaces (&header->lumps[LUMP_FACES], longm); } // Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]); if (noerrors) Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); - noerrors = noerrors && Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]); - noerrors = noerrors && Mod_LoadNodes (&header->lumps[LUMP_NODES]); - noerrors = noerrors && Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]); + noerrors = noerrors && Mod_LoadLeafs (&header->lumps[LUMP_LEAFS], longm); + noerrors = noerrors && Mod_LoadNodes (&header->lumps[LUMP_NODES], longm); + noerrors = noerrors && Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES], longm); if (noerrors) { Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]); diff --git a/engine/server/svq2_game.c b/engine/server/svq2_game.c index 885d7bc58..55ab0dc39 100644 --- a/engine/server/svq2_game.c +++ b/engine/server/svq2_game.c @@ -637,7 +637,7 @@ static model_t *SVQ2_GetCModel(world_t *w, int modelindex) void SVQ2_InitWorld(void) { - sv.world.GetCModel = SVQ2_GetCModel; + sv.world.Get_CModel = SVQ2_GetCModel; } qboolean SVQ2_InitGameProgs(void) diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index 1d19c6b0a..804899890 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -66,6 +66,7 @@ static int q3_num_snapshot_entities; static int q3_next_snapshot_entities; static q3entityState_t *q3_snapshot_entities; static q3entityState_t *q3_baselines; +extern cvar_t sv_pure; #define NUM_FOR_GENTITY(ge) (((char*)ge - (char*)q3_entarray) / sizeofq3gentity) #define NUM_FOR_SENTITY(se) (se - q3_sentities) @@ -1676,8 +1677,6 @@ qboolean SVQ3_InitGame(void) char buffer[8192]; char *str; char sysinfo[8192]; - extern cvar_t progs; - cvar_t *sv_pure; if (sv.world.worldmodel->type == mod_heightmap) { @@ -1688,7 +1687,7 @@ qboolean SVQ3_InitGame(void) return false; //always fail on q1bsp } - if (*progs.string) //don't load q3 gamecode if we're explicitally told to load a progs. + if (*pr_ssqc_progs.string) //don't load q3 gamecode if we're explicitally told to load a progs. return false; @@ -1705,11 +1704,13 @@ qboolean SVQ3_InitGame(void) q3_sentities = Z_Malloc(sizeof(q3serverEntity_t)*MAX_GENTITIES); + /*qw serverinfo settings are not normally visible in the q3 serverinfo*/ strcpy(buffer, svs.info); Info_SetValueForKey(buffer, "map", "", sizeof(buffer)); Info_SetValueForKey(buffer, "maxclients", "", sizeof(buffer)); Info_SetValueForKey(buffer, "mapname", sv.name, sizeof(buffer)); Info_SetValueForKey(buffer, "sv_maxclients", "32", sizeof(buffer)); + Info_SetValueForKey(buffer, "sv_pure", "", sizeof(buffer)); SVQ3_SetConfigString(0, buffer); Cvar_Set(Cvar_Get("sv_running", "0", 0, "Q3 compatability"), "1"); @@ -1720,17 +1721,16 @@ qboolean SVQ3_InitGame(void) str = FS_GetPackHashes(buffer, sizeof(buffer), false); Info_SetValueForKey(sysinfo, "sv_paks", str, MAX_SERVERINFO_STRING); - str = FS_GetPackNames(buffer, sizeof(buffer), false); + str = FS_GetPackNames(buffer, sizeof(buffer), false, false); Info_SetValueForKey(sysinfo, "sv_pakNames", str, MAX_SERVERINFO_STRING); str = FS_GetPackHashes(buffer, sizeof(buffer), true); Info_SetValueForKey(sysinfo, "sv_referencedPaks", str, MAX_SERVERINFO_STRING); - str = FS_GetPackNames(buffer, sizeof(buffer), true); + str = FS_GetPackNames(buffer, sizeof(buffer), true, false); Info_SetValueForKey(sysinfo, "sv_referencedPakNames", str, MAX_SERVERINFO_STRING); - sv_pure = Cvar_Get("sv_pure", "1", 0, "Q3 compatability"); - Info_SetValueForKey(sysinfo, "sv_pure", sv_pure->string, MAX_SERVERINFO_STRING); + Info_SetValueForKey(sysinfo, "sv_pure", sv_pure.string, MAX_SERVERINFO_STRING); SVQ3_SetConfigString(1, sysinfo); @@ -2133,8 +2133,8 @@ q3playerState_t *SVQ3Q1_BuildPlayerState(client_t *client) memset(&state, 0, sizeof(state)); -#ifdef _MSC_VER -#pragma message("qwoverq3: other things will need to be packed into here.") +#ifdef warningmsg +#pragma warningmsg("qwoverq3: other things will need to be packed into here.") #endif state.commandTime = client->lastcmd.servertime; @@ -2346,8 +2346,8 @@ void SVQ3_BuildClientSnapshot( client_t *client ) void SVQ3Q1_ConvertEntStateQ1ToQ3(entity_state_t *q1, q3entityState_t *q3) { -#ifdef _MSC_VER -#pragma message("qwoverq3: This _WILL_ need extending") +#ifdef warningmsg +#pragma warningmsg("qwoverq3: This _WILL_ need extending") #endif q3->number = q1->number; @@ -2862,8 +2862,8 @@ void SVQ3_ParseUsercmd(client_t *client, qboolean delta) { usercmd_t temp; temp = client->lastcmd; -#ifdef _MSC_VER -#pragma message("qwoverq3: you need to be aware of this if you're making a compatible cgame") +#ifdef warningmsg +#pragma warningmsg("qwoverq3: you need to be aware of this if you're making a compatible cgame") #endif //if you read the q3 code, you'll see that the speed value used is 64 for walking, and 127 for running (full speed). //so we map full to full here. diff --git a/engine/server/world.c b/engine/server/world.c index 8c3c80484..09b557fe9 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -1021,7 +1021,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v // get the clipping hull if (ent->v->solid == SOLID_BSP) { - model = w->GetCModel(w, ent->v->modelindex); + model = w->Get_CModel(w, ent->v->modelindex); if (!model || (model->type != mod_brush && model->type != mod_heightmap)) Host_Error("SOLID_BSP with non bsp model (classname: %s)", PR_GetString(w->progs, ent->v->classname)); } @@ -1056,7 +1056,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v model_t *model; if (ent->v->modelindex < 1 || ent->v->modelindex >= MAX_MODELS) Host_Error("SV_ClipMoveToEntity: modelindex out of range\n"); - model = w->GetCModel(w, ent->v->modelindex); + model = w->Get_CModel(w, ent->v->modelindex); if (model && model->funcs.Trace) { @@ -1081,7 +1081,7 @@ static trace_t WorldQ2_ClipMoveToEntity (world_t *w, q2edict_t *ent, vec3_t star // get the clipping hull if (ent->s.solid == Q2SOLID_BSP) { - model = w->GetCModel(w, ent->s.modelindex); + model = w->Get_CModel(w, ent->s.modelindex); if (!model || model->type != mod_brush) SV_Error("SOLID_BSP with non bsp model"); } @@ -1282,7 +1282,7 @@ static model_t *WorldQ2_ModelForEntity (world_t *w, q2edict_t *ent) // decide which clipping hull to use, based on the size if (ent->solid == Q2SOLID_BSP) { // explicit hulls in the BSP model - model = w->GetCModel(w, ent->s.modelindex); + model = w->Get_CModel(w, ent->s.modelindex); if (!model) SV_Error ("Q2SOLID_BSP with a non bsp model"); diff --git a/specs/browserexample.html b/specs/browserexample.html index decdc1b5c..8e0adc460 100644 --- a/specs/browserexample.html +++ b/specs/browserexample.html @@ -53,6 +53,12 @@ game specifies which game you are trying to target. Explicitly supported values /*set it to some server*/ fte.server = "192.168.0.1:27500"; /*explicitly activate it without requiring the user to click on it. only one plugin instance can be active at once. use with caution, or at least not on more than one plugin object on page site.*/ - fte.running = 1; +// fte.running = 1; document.write(fte.plugver); - \ No newline at end of file + + +
+run
+640*480
+800*600
+1024*768