From 559144cb059b2853ea59193ebd697fd0e4cb9077 Mon Sep 17 00:00:00 2001 From: Spoike Date: Sat, 9 Dec 2017 21:22:46 +0000 Subject: [PATCH] Updated font code for freecs's benefit. added cl_iDrive cvar. tried to solve invalid server address errors. fixed envmap+screenshot_cubemap commands (they write slightly different cubemaps). rework server favourites a little, to avoid conflicts with other engines. fix legacy rtlights on certain maps. added 'rgbgen entitylighting' for lighting with colormod support. decompiler should cope with more instructions now. pretty much just switch opcodes that are bugged now. implemented a couple of joint types into the bullet plugin. still useless though. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5180 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_input.c | 151 +++--- engine/client/cl_main.c | 5 + engine/client/cl_master.h | 2 + engine/client/cl_screen.c | 104 +++- engine/client/cl_ui.c | 1 + engine/client/client.h | 4 +- engine/client/image.c | 68 +-- engine/client/m_master.c | 1 + engine/client/m_options.c | 29 +- engine/client/menu.c | 3 + engine/client/net_master.c | 137 ++--- engine/client/r_2d.c | 5 +- engine/client/render.h | 4 +- engine/client/renderer.c | 4 +- engine/client/sbar.c | 7 +- engine/client/wad.c | 74 ++- engine/client/wad.h | 4 +- engine/client/zqtp.c | 2 +- engine/common/cmd.c | 63 ++- engine/common/com_mesh.c | 26 +- engine/common/com_phys_ode.c | 2 - engine/common/mathlib.h | 1 + engine/d3d/d3d11_backend.c | 2 +- engine/d3d/d3d_backend.c | 20 +- engine/gl/gl_backend.c | 32 +- engine/gl/gl_font.c | 663 ++++++++++++++++++------- engine/gl/gl_shader.c | 5 +- engine/gl/r_bishaders.h | 8 +- engine/gl/shader.h | 1 + engine/qclib/decomp.c | 23 +- engine/qclib/progsint.h | 7 +- engine/qclib/qcc_pr_comp.c | 607 +++++++++++----------- engine/server/pr_cmds.c | 8 +- engine/shaders/glsl/lpp_depthnorm.glsl | 8 +- engine/shaders/hlsl9/terrain.hlsl | 2 +- engine/vk/vk_backend.c | 26 +- fteqtv/protocol.h | 524 +++++++++---------- plugins/bullet/bulletplug.cpp | 356 +++++++------ 38 files changed, 1745 insertions(+), 1244 deletions(-) diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 22d8d7d3..a79eaf91 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -41,6 +41,7 @@ cvar_t cl_netfps = CVAR("cl_netfps", "150"); cvar_t cl_sparemsec = CVARC("cl_sparemsec", "10", CL_SpareMsec_Callback); cvar_t cl_queueimpulses = CVAR("cl_queueimpulses", "0"); cvar_t cl_smartjump = CVAR("cl_smartjump", "1"); +cvar_t cl_iDrive = CVARFD("cl_iDrive", "1", CVAR_SEMICHEAT, "Effectively releases movement keys when the opposing key is pressed. This avoids dead-time when both keys are pressed. This can be emulated with various scripts, but that's messy."); cvar_t cl_run = CVARD("cl_run", "0", "Enables autorun, inverting the state of the +speed key."); cvar_t cl_fastaccel = CVARD("cl_fastaccel", "1", "Begin moving at full speed instantly, instead of waiting a frame or so."); extern cvar_t cl_rollspeed; @@ -142,18 +143,19 @@ state bit 2 is edge triggered on the down to up transition */ -kbutton_t in_mlook, in_klook; -kbutton_t in_left, in_right, in_forward, in_back; -kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; -kbutton_t in_strafe, in_speed, in_use, in_jump, in_attack; -kbutton_t in_rollleft, in_rollright, in_up, in_down; +kbutton_t in_mlook, in_strafe, in_speed; +static kbutton_t in_klook; +static kbutton_t in_left, in_right, in_forward, in_back; +static kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright; +static kbutton_t in_use, in_jump, in_attack; +static kbutton_t in_rollleft, in_rollright, in_up, in_down; -kbutton_t in_button3, in_button4, in_button5, in_button6, in_button7, in_button8; +static kbutton_t in_button3, in_button4, in_button5, in_button6, in_button7, in_button8; #define IN_IMPULSECACHE 32 -int in_impulse[MAX_SPLITS][IN_IMPULSECACHE]; -int in_nextimpulse[MAX_SPLITS]; -int in_impulsespending[MAX_SPLITS]; +static int in_impulse[MAX_SPLITS][IN_IMPULSECACHE]; +static int in_nextimpulse[MAX_SPLITS]; +static int in_impulsespending[MAX_SPLITS]; qboolean cursor_active; @@ -161,7 +163,7 @@ qboolean cursor_active; -void KeyDown (kbutton_t *b) +static void KeyDown (kbutton_t *b, kbutton_t *anti) { int k; char *c; @@ -190,9 +192,17 @@ void KeyDown (kbutton_t *b) if (b->state[pnum] & 1) return; // still down b->state[pnum] |= 1 + 2; // down + impulse down + + if (anti && (anti->state[pnum] & 1) && cl_iDrive.ival) + { //anti-keys are the opposing key. so +forward can auto-release +back for slightly faster-responding keypresses. + b->suppressed[pnum] = anti; + anti->suppressed[pnum] = NULL; + anti->state[pnum] &= ~1; // now up + anti->state[pnum] |= 4; // impulse up + } } -void KeyUp (kbutton_t *b) +static void KeyUp (kbutton_t *b) { int k; char *c; @@ -204,6 +214,7 @@ void KeyUp (kbutton_t *b) k = atoi(c); else { // typed manually at the console, assume for unsticking, so clear all + b->suppressed[pnum] = NULL; b->down[pnum][0] = b->down[pnum][1] = 0; b->state[pnum] = 4; // impulse up return; @@ -222,54 +233,61 @@ void KeyUp (kbutton_t *b) return; // still up (this should not happen) b->state[pnum] &= ~1; // now up b->state[pnum] |= 4; // impulse up + + if (b->suppressed[pnum]) + { + if (b->suppressed[pnum]->down[pnum][0] || b->suppressed[pnum]->down[pnum][1]) + b->suppressed[pnum]->state[pnum] |= 1 + 2; + b->suppressed[pnum] = NULL; + } } -void IN_KLookDown (void) {KeyDown(&in_klook);} -void IN_KLookUp (void) {KeyUp(&in_klook);} -void IN_MLookDown (void) {KeyDown(&in_mlook);} -void IN_MLookUp (void) +static void IN_KLookDown (void) {KeyDown(&in_klook, NULL);} +static void IN_KLookUp (void) {KeyUp(&in_klook);} +static void IN_MLookDown (void) {KeyDown(&in_mlook, NULL);} +static void IN_MLookUp (void) { int pnum = CL_TargettedSplit(false); KeyUp(&in_mlook); if ( !(in_mlook.state[pnum]&1) && lookspring.ival) V_StartPitchDrift(&cl.playerview[pnum]); } -void IN_UpDown(void) {KeyDown(&in_up);} -void IN_UpUp(void) {KeyUp(&in_up);} -void IN_DownDown(void) {KeyDown(&in_down);} -void IN_DownUp(void) {KeyUp(&in_down);} -void IN_LeftDown(void) {KeyDown(&in_left);} -void IN_LeftUp(void) {KeyUp(&in_left);} -void IN_RightDown(void) {KeyDown(&in_right);} -void IN_RightUp(void) {KeyUp(&in_right);} -void IN_ForwardDown(void) {KeyDown(&in_forward);} -void IN_ForwardUp(void) {KeyUp(&in_forward);} -void IN_BackDown(void) {KeyDown(&in_back);} -void IN_BackUp(void) {KeyUp(&in_back);} -void IN_LookupDown(void) {KeyDown(&in_lookup);} -void IN_LookupUp(void) {KeyUp(&in_lookup);} -void IN_LookdownDown(void) {KeyDown(&in_lookdown);} -void IN_LookdownUp(void) {KeyUp(&in_lookdown);} -void IN_MoveleftDown(void) {KeyDown(&in_moveleft);} -void IN_MoveleftUp(void) {KeyUp(&in_moveleft);} -void IN_MoverightDown(void) {KeyDown(&in_moveright);} -void IN_MoverightUp(void) {KeyUp(&in_moveright);} -void IN_RollLeftDown(void) {KeyDown(&in_rollleft);} -void IN_RollLeftUp(void) {KeyUp(&in_rollleft);} -void IN_RollRightDown(void) {KeyDown(&in_rollright);} -void IN_RollRightUp(void) {KeyUp(&in_rollright);} +static void IN_UpDown(void) {KeyDown(&in_up, &in_down);} +static void IN_UpUp(void) {KeyUp(&in_up);} +static void IN_DownDown(void) {KeyDown(&in_down, &in_up);} +static void IN_DownUp(void) {KeyUp(&in_down);} +static void IN_LeftDown(void) {KeyDown(&in_left, &in_right);} +static void IN_LeftUp(void) {KeyUp(&in_left);} +static void IN_RightDown(void) {KeyDown(&in_right, &in_left);} +static void IN_RightUp(void) {KeyUp(&in_right);} +static void IN_ForwardDown(void) {KeyDown(&in_forward, &in_back);} +static void IN_ForwardUp(void) {KeyUp(&in_forward);} +static void IN_BackDown(void) {KeyDown(&in_back, &in_forward);} +static void IN_BackUp(void) {KeyUp(&in_back);} +static void IN_LookupDown(void) {KeyDown(&in_lookup, &in_lookdown);} +static void IN_LookupUp(void) {KeyUp(&in_lookup);} +static void IN_LookdownDown(void) {KeyDown(&in_lookdown, &in_lookup);} +static void IN_LookdownUp(void) {KeyUp(&in_lookdown);} +static void IN_MoveleftDown(void) {KeyDown(&in_moveleft, &in_moveright);} +static void IN_MoveleftUp(void) {KeyUp(&in_moveleft);} +static void IN_MoverightDown(void) {KeyDown(&in_moveright, &in_moveleft);} +static void IN_MoverightUp(void) {KeyUp(&in_moveright);} +static void IN_RollLeftDown(void) {KeyDown(&in_rollleft, &in_rollright);} +static void IN_RollLeftUp(void) {KeyUp(&in_rollleft);} +static void IN_RollRightDown(void) {KeyDown(&in_rollright, &in_rollleft);} +static void IN_RollRightUp(void) {KeyUp(&in_rollright);} -void IN_SpeedDown(void) {KeyDown(&in_speed);} -void IN_SpeedUp(void) {KeyUp(&in_speed);} -void IN_StrafeDown(void) {KeyDown(&in_strafe);} -void IN_StrafeUp(void) {KeyUp(&in_strafe);} +static void IN_SpeedDown(void) {KeyDown(&in_speed, NULL);} +static void IN_SpeedUp(void) {KeyUp(&in_speed);} +static void IN_StrafeDown(void) {KeyDown(&in_strafe, NULL);} +static void IN_StrafeUp(void) {KeyUp(&in_strafe);} -void IN_AttackDown(void) {KeyDown(&in_attack);} -void IN_AttackUp(void) {KeyUp(&in_attack);} +static void IN_AttackDown(void) {KeyDown(&in_attack, NULL);} +static void IN_AttackUp(void) {KeyUp(&in_attack);} -void IN_UseDown (void) {KeyDown(&in_use);} -void IN_UseUp (void) {KeyUp(&in_use);} -void IN_JumpDown (void) +static void IN_UseDown (void) {KeyDown(&in_use, NULL);} +static void IN_UseUp (void) {KeyUp(&in_use);} +static void IN_JumpDown (void) { qboolean condition; @@ -281,7 +299,7 @@ void IN_JumpDown (void) condition = (cls.state == ca_active && cl_smartjump.ival && !prox_inmenu.ival); #ifdef Q2CLIENT if (condition && cls.protocol == CP_QUAKE2) - KeyDown(&in_up); + KeyDown(&in_up, &in_down); else #endif #ifdef QUAKESTATS @@ -289,36 +307,36 @@ void IN_JumpDown (void) (cls.protocol==CP_NETQUAKE || cl.inframes[cl.validsequence&UPDATE_MASK].playerstate[pv->playernum].messagenum == cl.validsequence) && cl.playerview[pnum].waterlevel >= 2 && (!cl.teamfortress || !(in_forward.state[pnum] & 1)) ) - KeyDown(&in_up); + KeyDown(&in_up, &in_down); else #endif if (condition && pv->spectator && pv->cam_state == CAM_FREECAM) - KeyDown(&in_up); + KeyDown(&in_up, &in_down); else - KeyDown(&in_jump); + KeyDown(&in_jump, &in_down); } -void IN_JumpUp (void) +static void IN_JumpUp (void) { if (cl_smartjump.ival) KeyUp(&in_up); KeyUp(&in_jump); } -void IN_Button3Down(void) {KeyDown(&in_button3);} -void IN_Button3Up(void) {KeyUp(&in_button3);} -void IN_Button4Down(void) {KeyDown(&in_button4);} -void IN_Button4Up(void) {KeyUp(&in_button4);} -void IN_Button5Down(void) {KeyDown(&in_button5);} -void IN_Button5Up(void) {KeyUp(&in_button5);} -void IN_Button6Down(void) {KeyDown(&in_button6);} -void IN_Button6Up(void) {KeyUp(&in_button6);} -void IN_Button7Down(void) {KeyDown(&in_button7);} -void IN_Button7Up(void) {KeyUp(&in_button7);} -void IN_Button8Down(void) {KeyDown(&in_button8);} -void IN_Button8Up(void) {KeyUp(&in_button8);} +static void IN_Button3Down(void) {KeyDown(&in_button3, NULL);} +static void IN_Button3Up(void) {KeyUp(&in_button3);} +static void IN_Button4Down(void) {KeyDown(&in_button4, NULL);} +static void IN_Button4Up(void) {KeyUp(&in_button4);} +static void IN_Button5Down(void) {KeyDown(&in_button5, NULL);} +static void IN_Button5Up(void) {KeyUp(&in_button5);} +static void IN_Button6Down(void) {KeyDown(&in_button6, NULL);} +static void IN_Button6Up(void) {KeyUp(&in_button6);} +static void IN_Button7Down(void) {KeyDown(&in_button7, NULL);} +static void IN_Button7Up(void) {KeyUp(&in_button7);} +static void IN_Button8Down(void) {KeyDown(&in_button8, NULL);} +static void IN_Button8Up(void) {KeyUp(&in_button8);} float in_rotate; -void IN_Rotate_f (void) {in_rotate += atoi(Cmd_Argv(1));} +static void IN_Rotate_f (void) {in_rotate += atoi(Cmd_Argv(1));} void IN_WriteButtons(vfsfile_t *f, qboolean all) @@ -2183,6 +2201,7 @@ void CL_InitInput (void) Cvar_Register (&cl_netfps, inputnetworkcvargroup); Cvar_Register (&cl_sparemsec, inputnetworkcvargroup); Cvar_Register (&cl_run, inputnetworkcvargroup); + Cvar_Register (&cl_iDrive, inputnetworkcvargroup); #ifdef NQPROT Cvar_Register (&cl_movement, inputnetworkcvargroup); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 1bee6194..503b192e 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1223,6 +1223,7 @@ void CL_Connect_f (void) } server = Cmd_Argv (1); + server = strcpy(alloca(strlen(server)+1), server); #ifndef CLIENTONLY if (sv.state == ss_clustermode) @@ -1289,6 +1290,7 @@ static void CL_Join_f (void) } server = Cmd_Argv (1); + server = strcpy(alloca(strlen(server)+1), server); CL_Disconnect_f (); @@ -1316,6 +1318,7 @@ void CL_Observe_f (void) } server = Cmd_Argv (1); + server = strcpy(alloca(strlen(server)+1), server); CL_Disconnect_f (); @@ -1336,6 +1339,7 @@ void CLNQ_Connect_f (void) } server = Cmd_Argv (1); + server = strcpy(alloca(strlen(server)+1), server); CL_Disconnect_f (); @@ -1658,6 +1662,7 @@ void CL_ClearState (void) if (cfg_save_auto.ival && Cvar_UnsavedArchive()) Cmd_ExecuteString("cfg_save\n", RESTRICT_LOCAL); + MasterInfo_WriteServers(); } /* diff --git a/engine/client/cl_master.h b/engine/client/cl_master.h index a5c4beaf..52e78708 100644 --- a/engine/client/cl_master.h +++ b/engine/client/cl_master.h @@ -198,11 +198,13 @@ void SListOptionChanged(serverinfo_t *newserver); extern serverinfo_t *firstserver; extern master_t *master; extern player_t *mplayers; +extern qboolean sb_favouriteschanged; void Master_SetupSockets(void); qboolean CL_QueryServers(void); int Master_CheckPollSockets(void); void MasterInfo_Shutdown(void); +void MasterInfo_WriteServers(void); void MasterInfo_Request(master_t *mast); serverinfo_t *Master_InfoForServer (netadr_t *addr); serverinfo_t *Master_InfoForNum (int num); diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index eed5b2fe..0c1207cf 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -2927,37 +2927,110 @@ void SCR_ScreenShot_Cubemap_f(void) uploadfmt_t fmt; char filename[MAX_QPATH]; char *fname = Cmd_Argv(1); - int i; + int i, firstside; + char olddrawviewmodel[64]; //hack, so we can set r_drawviewmodel to 0 so that it doesn't appear in screenshots even if the csqc is generating new data. + vec3_t oldangles; const struct { vec3_t angle; const char *postfix; + qboolean verticalflip; + qboolean horizontalflip; } sides[] = { - {{0, 0, 0}, "_px"}, - {{0, 180, 0}, "_nx"}, - {{0, 90, 0}, "_py"}, - {{0, 270, 0}, "_ny"}, - {{90, 0, 0}, "_pz"}, - {{-90, 0, 0}, "_nz"} + //standard cubemap + {{0, 0, 90}, "_px", true}, + {{0, 180, -90}, "_nx", true}, + {{0, 90, 0}, "_py", true}, //upside down + {{0, 270, 0}, "_ny", false, true}, + {{-90, 0, 90}, "_pz", true}, + {{90, 0, 90}, "_nz", true}, + + //annoying envmap (requires processing to flip/etc the images before they can be loaded into a texture) + {{0, 270, 0}, "_ft"}, + {{0, 90, 0}, "_bk"}, + {{0, 0, 0}, "_rt"}, + {{0, 180, 0}, "_lf"}, + {{90, 0, 0}, "_dn"}, + {{-90, 0, 0}, "_up"} }; - r_refdef.stereomethod = STEREO_OFF; + if (!cls.state || !cl.worldmodel || cl.worldmodel->loadstate != MLS_LOADED) + { + Con_Printf("Please start a map first\n"); + return; + } - fbheight = atoi(Cmd_Argv(2)); + firstside = strcmp(Cmd_Argv(0), "envmap")?0:6; + + r_refdef.stereomethod = STEREO_OFF; + Q_strncpyz(olddrawviewmodel, r_drawviewmodel.string, sizeof(olddrawviewmodel)); + Cvar_Set(&r_drawviewmodel, "0"); + + VectorCopy(cl.playerview->viewangles, oldangles); + + fbheight = atoi(Cmd_Argv(2))&~1; if (fbheight < 1) fbheight = 512; fbwidth = fbheight; - for (i = 0; i < countof(sides); i++) + for (i = firstside; i < firstside+6; i++) { - Q_snprintfz(filename, sizeof(filename), "cubemaps/%s%s", fname, sides[i].postfix); + if (!*fname) + { + char base[MAX_QPATH]; + COM_FileBase(cl.worldmodel->name, base, sizeof(base)); + fname = va("%s/%i_%i_%i", base, (int)r_refdef.vieworg[0], (int)r_refdef.vieworg[1], (int)r_refdef.vieworg[2]); + } + Q_snprintfz(filename, sizeof(filename), "textures/%s%s", fname, sides[i].postfix); COM_DefaultExtension (filename, scr_sshot_type.string, sizeof(filename)); + VectorCopy(sides[i].angle, cl.playerview->simangles); + VectorCopy(cl.playerview->simangles, cl.playerview->viewangles); + buffer = SCR_ScreenShot_Capture(fbwidth, fbheight, &stride, &fmt); if (buffer) { char sysname[1024]; + if (sides[i].horizontalflip) + { + int y, x, p; + int pxsize; + char *bad = buffer; + char *in = buffer, *out; + switch(fmt) + { + case TF_RGBA32: + case TF_BGRA32: + case TF_RGBX32: + case TF_BGRX32: + pxsize = 4; + break; + case TF_RGB24: + case TF_BGR24: + pxsize = 3; + break; + default: //erk! + pxsize = 1; + break; + } + buffer = out = BZ_Malloc(fbwidth*fbheight*pxsize); + for (y = 0; y < fbheight; y++, in += abs(stride), out += fbwidth*pxsize) + { + for (x = 0; x < fbwidth*pxsize; x+=pxsize) + { + for (p = 0; p < pxsize; p++) + out[x+p] = in[(fbwidth-1)*pxsize-x+p]; + } + } + BZ_Free(bad); + if (stride < 0) + stride = -fbwidth*pxsize; + else + stride = fbwidth*pxsize; + } + if (sides[i].verticalflip) + stride = -stride; if (SCR_ScreenShot(filename, FS_GAMEONLY, &buffer, 1, stride, fbwidth, fbheight, fmt)) { FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname)); @@ -2971,6 +3044,10 @@ void SCR_ScreenShot_Cubemap_f(void) BZ_Free(buffer); } } + + Cvar_Set(&r_drawviewmodel, olddrawviewmodel); + + VectorCopy(oldangles, cl.playerview->viewangles); } @@ -2987,7 +3064,10 @@ static void SCR_DrawCharToSnap (int num, qbyte *dest, int width) if (!draw_chars) { size_t lumpsize; - draw_chars = W_SafeGetLumpName("conchars", &lumpsize); + qbyte lumptype; + draw_chars = W_GetLumpName("conchars", &lumpsize, &lumptype); +// if (lumptype != ) +// draw_chars = NULL; if (!draw_chars || lumpsize != 128*128) return; } diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index 60296ff8..a7710787 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -1598,6 +1598,7 @@ void UI_Stop (void) //note that q3 checks every frame. we only check when the ui is closed. if (Cvar_UnsavedArchive()) Cmd_ExecuteString("cfg_save", RESTRICT_LOCAL); + MasterInfo_WriteServers(); } } diff --git a/engine/client/client.h b/engine/client/client.h index f69fb38a..0437ad9a 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -1111,10 +1111,12 @@ entity_t *TraceLineR (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); // // cl_input // -typedef struct +typedef struct kbutton_s { int down[MAX_SPLITS][2]; // key nums holding it down int state[MAX_SPLITS]; // low bit is down state + + struct kbutton_s *suppressed[MAX_SPLITS]; //the button that was suppressed by this one getting pressed } kbutton_t; extern kbutton_t in_mlook; diff --git a/engine/client/image.c b/engine/client/image.c index 7de60b0d..ef977b8f 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -228,7 +228,7 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, qboolean * return NULL; } //validate the size to some sanity limit. - if ((unsigned short)tgaheader.width > 8192 || (unsigned short)tgaheader.height > 8192) + if ((unsigned short)tgaheader.width > 16384 || (unsigned short)tgaheader.height > 16384) return NULL; @@ -2589,8 +2589,9 @@ static void Image_LoadTextureMips(void *ctx, void *data, size_t a, size_t b) if (!strncmp(tex->ident, "gfx/", 4)) { size_t lumpsize; - qpic_t *pic = W_SafeGetLumpName(tex->ident+4, &lumpsize); - if (pic && lumpsize == 8 + pic->width*pic->height) + qbyte lumptype; + qpic_t *pic = W_GetLumpName(tex->ident+4, &lumpsize, &lumptype); + if (pic && lumptype == TYP_QPIC && lumpsize == 8 + pic->width*pic->height) { tex->width = pic->width; tex->height = pic->height; @@ -3464,6 +3465,7 @@ static void Image_GenerateMips(struct pendingtextureinfo *mips, unsigned int fla } //stolen from DP +//FIXME: optionally support borders as 0,0,0,0 static void Image_Resample32LerpLine (const qbyte *in, qbyte *out, int inwidth, int outwidth) { int j, xi, oldx = 0, f, fstep, endx, lerp; @@ -3497,15 +3499,16 @@ static void Image_Resample32LerpLine (const qbyte *in, qbyte *out, int inwidth, //yes, this is lordhavok's code too. //superblur away! +//FIXME: optionally support borders as 0,0,0,0 #define LERPBYTE(i) r = row1[i];out[i] = (qbyte) ((((row2[i] - r) * lerp) >> 16) + r) static void Image_Resample32Lerp(const void *indata, int inwidth, int inheight, void *outdata, int outwidth, int outheight) { int i, j, r, yi, oldy, f, fstep, lerp, endy = (inheight-1), inwidth4 = inwidth*4, outwidth4 = outwidth*4; qbyte *out; const qbyte *inrow; - qbyte *tmem, *row1, *row2; + qbyte *row1, *row2; - tmem = row1 = BZ_Malloc(2*(outwidth*4)); + row1 = alloca(2*(outwidth*4)); row2 = row1 + (outwidth * 4); out = outdata; @@ -3584,6 +3587,7 @@ static void Image_Resample32Lerp(const void *indata, int inwidth, int inheight, } else { + yi = endy; //don't read off the end if (yi != oldy) { inrow = (qbyte *)indata + inwidth4*yi; @@ -3594,9 +3598,9 @@ static void Image_Resample32Lerp(const void *indata, int inwidth, int inheight, oldy = yi; } memcpy(out, row1, outwidth4); + out += outwidth4; //Fixes a bug from DP. } } - BZ_Free(tmem); } @@ -4802,28 +4806,34 @@ struct pendingtextureinfo *Image_LoadCubemapTextureData(const char *nicename, ch { char *suffix; qboolean flipx, flipy, flipd; - } cmscheme[] = + } cmscheme[][6] = { - {"rt", true, false, true}, - {"lf", false, true, true}, - {"ft", true, true, false}, - {"bk", false, false, false}, - {"up", true, false, true}, - {"dn", true, false, true}, + { + {"rt", true, false, true}, + {"lf", false, true, true}, + {"ft", true, true, false}, + {"bk", false, false, false}, + {"up", true, false, true}, + {"dn", true, false, true} + }, - {"px", false, false, false}, - {"nx", false, false, false}, - {"py", false, false, false}, - {"ny", false, false, false}, - {"pz", false, false, false}, - {"nz", false, false, false}, + { + {"px", false, false, false}, + {"nx", false, false, false}, + {"py", false, false, false}, + {"ny", false, false, false}, + {"pz", false, false, false}, + {"nz", false, false, false} + }, - {"posx", false, false, false}, - {"negx", false, false, false}, - {"posy", false, false, false}, - {"negy", false, false, false}, - {"posz", false, false, false}, - {"negz", false, false, false} + { + {"posx", false, false, false}, + {"negx", false, false, false}, + {"posy", false, false, false}, + {"negy", false, false, false}, + {"posz", false, false, false}, + {"negz", false, false, false} + } }; int i, j, e; struct pendingtextureinfo *mips; @@ -4851,14 +4861,14 @@ struct pendingtextureinfo *Image_LoadCubemapTextureData(const char *nicename, ch qbyte *buf = NULL, *data; filesize = 0; - for (j = 0; j < sizeof(cmscheme)/sizeof(cmscheme[0])/6; j++) + for (j = 0; j < countof(cmscheme); j++) { - Q_snprintfz(fname+prefixlen, sizeof(fname)-prefixlen, "%s_%s%s", nicename, cmscheme[i + 6*j].suffix, tex_extensions[e].name); + Q_snprintfz(fname+prefixlen, sizeof(fname)-prefixlen, "%s_%s%s", nicename, cmscheme[j][i].suffix, tex_extensions[e].name); buf = COM_LoadFile(fname, 5, &filesize); if (buf) break; - Q_snprintfz(fname+prefixlen, sizeof(fname)-prefixlen, "%s%s%s", nicename, cmscheme[i + 6*j].suffix, tex_extensions[e].name); + Q_snprintfz(fname+prefixlen, sizeof(fname)-prefixlen, "%s%s%s", nicename, cmscheme[j][i].suffix, tex_extensions[e].name); buf = COM_LoadFile(fname, 5, &filesize); if (buf) break; @@ -4874,7 +4884,7 @@ struct pendingtextureinfo *Image_LoadCubemapTextureData(const char *nicename, ch { //(skies have a fallback for invalid sizes, but it'll run a bit slower) if (!(texflags&IF_NOGAMMA) && !vid_hardwaregamma.value) BoostGamma(data, width, height); - mips->mip[i].data = R_FlipImage32(data, &width, &height, cmscheme[i + 6*j].flipx, cmscheme[i + 6*j].flipy, cmscheme[i + 6*j].flipd); + mips->mip[i].data = R_FlipImage32(data, &width, &height, cmscheme[j][i].flipx, cmscheme[j][i].flipy, cmscheme[j][i].flipd); mips->mip[i].datasize = width*height*4; mips->mip[i].width = width; mips->mip[i].height = height; diff --git a/engine/client/m_master.c b/engine/client/m_master.c index 63125951..d81173d7 100644 --- a/engine/client/m_master.c +++ b/engine/client/m_master.c @@ -353,6 +353,7 @@ static qboolean SL_ServerKey (menucustom_t *ths, menu_t *menu, int key, unsigned if (server) { server->special ^= SS_FAVORITE; + sb_favouriteschanged = true; } } diff --git a/engine/client/m_options.c b/engine/client/m_options.c index e2e50ddc..8e91ef9d 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -977,7 +977,34 @@ void FPS_Preset_f (void) { char buffer[MAX_OSPATH]; COM_QuotedString(presetfname, buffer, sizeof(buffer), false); - Cbuf_AddText(va("\nexec %s\nfs_restart\n", buffer), RESTRICT_LOCAL); + Cbuf_InsertText(va("\nexec %s\nfs_restart\n", buffer), RESTRICT_LOCAL, false); + return; + } + + if (!stricmp("timedemo", arg)) + { + //some extra things to pwn timedemos. + Cbuf_InsertText( + "fps_preset fast\n" + "set r_renderscale 1\n" + "set contrast 1\n" + "set gamma 1\n" + "set brightness 0\n" + "set scr_autoid 0\n" + "set scr_autoid_team 0\n" + "set r_dynamic 0\n" + "set sbar_teamstatus 2\n" + "set gl_polyblend 0\n" +#if 1 + //these are cheaty settings. + "set gl_flashblend 0\n" + "set cl_predict_players 0\n" //very cheaty. you won't realise its off, but noone would disable it for actual play. +#else + //to make things fair + "set gl_flashblend 1\n" + "set r_part_density 1\n" +#endif + , RESTRICT_LOCAL, false); return; } diff --git a/engine/client/menu.c b/engine/client/menu.c index 79f8ac8b..407d1a5f 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "winquake.h" #include "shader.h" +#include "cl_master.h" qboolean menu_mousedown; @@ -1068,6 +1069,8 @@ void M_Menu_Quit_f (void) extern cvar_t cfg_save_auto; char *arg = Cmd_Argv(1); + MasterInfo_WriteServers(); + if (!strcmp(arg, "force")) mode = 0; else if (!strcmp(arg, "forcesave") || cfg_save_auto.ival) diff --git a/engine/client/net_master.c b/engine/client/net_master.c index e95355da..292150bf 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -6,6 +6,9 @@ clientside master queries and server ping/polls #include "quakedef.h" #include "cl_master.h" +#define FAVOURITESFILE "favourites.txt" + +qboolean sb_favouriteschanged; //some server's favourite flag got changed. we'll need to resave the list. qboolean sb_enablequake2; qboolean sb_enablequake3; qboolean sb_enablenetquake; @@ -585,7 +588,7 @@ void SV_Master_Shutdown (void) //the number of servers should be limited only by memory. cvar_t slist_cacheinfo = CVAR("slist_cacheinfo", "0"); //this proves dangerous, memory wise. -cvar_t slist_writeserverstxt = CVAR("slist_writeservers", "0"); +cvar_t slist_writeserverstxt = CVAR("slist_writeservers", "1"); void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad); int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favorite); @@ -2488,110 +2491,44 @@ void MasterInfo_Request(master_t *mast) void MasterInfo_WriteServers(void) { - char *typename, *protoname; - master_t *mast; serverinfo_t *server; - vfsfile_t *mf, *qws; + vfsfile_t *qws; char adr[MAX_ADR_SIZE]; - mf = FS_OpenVFS("masters.txt", "wt", FS_ROOT); - if (!mf) + if (slist_writeserverstxt.ival && sb_favouriteschanged) { - Con_Printf(CON_ERROR "Couldn't write masters.txt"); - return; - } - - for (mast = master; mast; mast=mast->next) - { - if (mast->nosave) - continue; - - switch(mast->mastertype) + qws = FS_OpenVFS(FAVOURITESFILE, "wt", FS_ROOT); + if (qws) { - case MT_MASTERUDP: - typename = "master"; - break; - case MT_MASTERHTTP: - typename = "masterhttp"; - break; - case MT_MASTERHTTPJSON: - typename = "masterjson"; - break; - case MT_BCAST: - typename = "bcast"; - break; - case MT_SINGLE: - typename = "single"; - break; - default: - typename = "??"; - break; - } - switch(mast->protocoltype) - { - case MP_QUAKEWORLD: - protoname = ":qw"; - break; - case MP_QUAKE2: - protoname = ":q2"; - break; - case MP_QUAKE3: - protoname = ":q3"; - break; - case MP_NETQUAKE: - protoname = ":nq"; - break; - case MP_DPMASTER: - protoname = ":dp"; - break; - default: - case MP_UNSPECIFIED: - protoname = ""; - break; - } - if (mast->address) - VFS_PUTS(mf, va("%s\t%s%s\t%s\n", mast->address, typename, protoname, mast->name)); - else - VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &mast->adr), typename, mast->name)); - } - - if (slist_writeserverstxt.value) - qws = FS_OpenVFS("servers.txt", "wt", FS_ROOT); - else - qws = NULL; - if (qws) - VFS_PUTS(mf, va("\n%s\t%s\t%s\n\n", "file servers.txt", "favorite:qw", "personal server list")); - - for (server = firstserver; server; server = server->next) - { - if (server->special & SS_FAVORITE) - { - switch(server->special & SS_PROTOCOLMASK) + sb_favouriteschanged = false; + for (server = firstserver; server; server = server->next) { - case SS_QUAKE3: - VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), "favorite:q3", server->name)); - break; - case SS_QUAKE2: - VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), "favorite:q2", server->name)); - break; - case SS_NETQUAKE: - VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), "favorite:nq", server->name)); - break; - case SS_QUAKEWORLD: - if (qws) //servers.txt doesn't support the extra info, so don't write it if its not needed - VFS_PUTS(qws, va("%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), server->name)); - else - VFS_PUTS(mf, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), "favorite:qw", server->name)); - break; + if (server->special & SS_FAVORITE) + { + switch(server->special & SS_PROTOCOLMASK) + { + case SS_QUAKE3: + VFS_PUTS(qws, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), "favorite:q3", server->name)); + break; + case SS_QUAKE2: + VFS_PUTS(qws, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), "favorite:q2", server->name)); + break; + case SS_NETQUAKE: + VFS_PUTS(qws, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), "favorite:nq", server->name)); + break; +// case SS_DARKPLACES: +// VFS_PUTS(qws, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), "favorite:dp", server->name)); +// break; + case SS_QUAKEWORLD: + VFS_PUTS(qws, va("%s\t%s\t%s\n", NET_AdrToString(adr, sizeof(adr), &server->adr), "favorite:qw", server->name)); + break; + } + } } + + VFS_CLOSE(qws); } } - - if (qws) - VFS_CLOSE(qws); - - - VFS_CLOSE(mf); } //poll master servers for server lists. @@ -2602,11 +2539,15 @@ void MasterInfo_Refresh(void) loadedone = false; loadedone |= Master_LoadMasterList("masters.txt", false, MT_MASTERUDP, MP_QUAKEWORLD, 5); //fte listing - loadedone |= Master_LoadMasterList("sources.txt", true, MT_MASTERUDP, MP_QUAKEWORLD, 5); //merge with ezquake compat listing + + Master_LoadMasterList(FAVOURITESFILE, false, MT_MASTERUDP, MP_QUAKEWORLD, 1); if (!loadedone) { int i; + + Master_LoadMasterList("sources.txt", true, MT_MASTERUDP, MP_QUAKEWORLD, 5); //merge with ezquake compat listing + Master_LoadMasterList("servers.txt", false, MT_MASTERUDP, MP_QUAKEWORLD, 1); Master_AddMaster("255.255.255.255:"STRINGIFY(PORT_QWSERVER), MT_BCAST, MP_QUAKEWORLD, "Nearby QuakeWorld UDP servers."); @@ -3030,7 +2971,7 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor name = Info_ValueForKey(msg, "sv_hostname"); Q_strncpyz(info->name, name, sizeof(info->name)); info->special = info->special & (SS_FAVORITE | SS_KEEPINFO | SS_LOCAL); //favorite+local is never cleared - if (!strcmp(DISTRIBUTION, Info_ValueForKey(msg, "*distrib"))) + if (!strcmp(DISTRIBUTION, Info_ValueForKey(msg, "*distrib"))) //outdated info->special |= SS_FTESERVER; else if (!strncmp(DISTRIBUTION, Info_ValueForKey(msg, "*version"), strlen(DISTRIBUTION))) info->special |= SS_FTESERVER; diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index f9df941f..bc7b1585 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -429,8 +429,9 @@ apic_t *R2D_LoadAtlasedPic(const char *name) if (!gl_load24bit.ival) { size_t lumpsize; - qp = W_SafeGetLumpName(name, &lumpsize); - if (qp && lumpsize == 8+qp->width*qp->height) + qbyte lumptype; + qp = W_GetLumpName(name, &lumpsize, &lumptype); + if (qp && lumptype == TYP_QPIC && lumpsize == 8+qp->width*qp->height) { apic->width = qp->width; apic->height = qp->height; diff --git a/engine/client/render.h b/engine/client/render.h index 4c72feba..7c333026 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -318,8 +318,8 @@ void BE_GenModelBatches(struct batch_s **batches, const struct dlight_s *dl, uns void R_GAliasFlushSkinCache(qboolean final); void R_GAlias_DrawBatch(struct batch_s *batch); void R_GAlias_GenerateBatches(entity_t *e, struct batch_s **batches); -void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t *colours, int vertcount, vec3_t *normals); -void R_LightArrays(const entity_t *entity, vecV_t *coords, vec4_t *colours, int vertcount, vec3_t *normals, float scale); +void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t *colours, int vertcount, vec3_t *normals, qboolean colormod); +void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *normals, float scale, qboolean colormod); qboolean R_DrawSkyChain (struct batch_s *batch); /*called from the backend, and calls back into it*/ void R_InitSky (shader_t *shader, const char *skyname, qbyte *src, unsigned int width, unsigned int height); /*generate q1 sky texnums*/ diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 504e1f5d..1b90e5fd 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -343,7 +343,7 @@ cvar_t gl_conback = CVARFCD ("gl_conback", "", //cvar_t gl_detail = CVARF ("gl_detail", "0", // CVAR_ARCHIVE); //cvar_t gl_detailscale = CVAR ("gl_detailscale", "5"); -cvar_t gl_font = CVARFD ("gl_font", "", +cvar_t gl_font = CVARAFD ("gl_font", "", "gl_consolefont", CVAR_RENDERERCALLBACK|CVAR_ARCHIVE, ("Specifies the font file to use. a value such as FONT:ALTFONT specifies an alternative font to be used when ^^a is used.\n" "When using TTF fonts, you will likely need to scale text to at least 150% - vid_conautoscale 1.5 will do this.\n" "TTF fonts may be loaded from your windows directory. \'gl_font cour?col=1,1,1:couri?col=0,1,0\' loads eg: c:\\windows\\fonts\\cour.ttf, and uses the italic version of courier for alternative text, with specific colour tints." @@ -401,7 +401,7 @@ cvar_t gl_mipcap = CVARAFC("d_mipcap", "0 1000", "gl_miptexLevel", cvar_t gl_texturemode2d = CVARFCD("gl_texturemode2d", "GL_LINEAR", CVAR_ARCHIVE | CVAR_RENDERERCALLBACK, Image_TextureMode_Callback, "Specifies how 2d images are sampled. format is a 3-tupple "); -cvar_t r_font_linear = CVARF("r_font_linear", "1", CVAR_RENDERERLATCH); +cvar_t r_font_linear = CVARF("r_font_linear", "1", 0); cvar_t vid_triplebuffer = CVARAFD ("vid_triplebuffer", "1", "gl_triplebuffer", CVAR_ARCHIVE, "Specifies whether the hardware is forcing tripplebuffering on us, this is the number of extra page swaps required before old data has been completely overwritten."); diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 6aa40928..9f28861b 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -953,6 +953,7 @@ void Sbar_Start (void) //if one of these fails, skip the entire status bar. { int i; size_t lumpsize; + qbyte lumptype; if (sbar_loaded) return; @@ -976,7 +977,7 @@ void Sbar_Start (void) //if one of these fails, skip the entire status bar. #ifdef HEXEN2 sbar_hexen2 = false; - if (W_SafeGetLumpName("tinyfont", &lumpsize)) + if (W_GetLumpName("tinyfont", &lumpsize, &lumptype)) sbar_hexen2 = true; // if (sb_nums[0][0] && sb_nums[0][0]->width < 13) // sbar_hexen2 = true; @@ -1057,7 +1058,7 @@ void Sbar_Start (void) //if one of these fails, skip the entire status bar. sb_scorebar = Sbar_PicFromWad ("scorebar"); //try to detect rogue wads, and thus the stats we will be getting from the server. - sbar_rogue = COM_CheckParm("-rogue") || !!W_SafeGetLumpName("r_lava", &lumpsize); + sbar_rogue = COM_CheckParm("-rogue") || !!W_GetLumpName("r_lava", &lumpsize, &lumptype); if (sbar_rogue) { rsb_invbar[0] = Sbar_PicFromWad ("r_invbar1"); @@ -1079,7 +1080,7 @@ void Sbar_Start (void) //if one of these fails, skip the entire status bar. rsb_ammo[2] = Sbar_PicFromWad ("r_ammoplasma"); } - sbar_hipnotic = COM_CheckParm("-hipnotic") || !!W_SafeGetLumpName("inv_mjolnir", &lumpsize); + sbar_hipnotic = COM_CheckParm("-hipnotic") || !!W_GetLumpName("inv_mjolnir", &lumpsize, &lumptype); if (sbar_hipnotic) { hsb_weapons[0][0] = Sbar_PicFromWad ("inv_laser"); diff --git a/engine/client/wad.c b/engine/client/wad.c index 459bd0ba..6a511ee4 100644 --- a/engine/client/wad.c +++ b/engine/client/wad.c @@ -113,7 +113,7 @@ void W_LoadWadFile (char *filename) if (header->identification[0] != 'W' || header->identification[1] != 'A' || header->identification[2] != 'D' - || header->identification[3] != '2') + || (header->identification[3] != '2' && header->identification[3] != '3')) { Con_Printf ("W_LoadWadFile: Wad file %s doesn't have WAD2 id\n",filename); wad_numlumps = 0; @@ -138,32 +138,17 @@ void W_LoadWadFile (char *filename) /* ============= -W_GetLumpinfo +W_GetLumpName ============= */ -/*lumpinfo_t *W_GetLumpinfo (char *name) +void *W_GetLumpName (const char *name, size_t *size, qbyte *type) { int i; lumpinfo_t *lump_p; char clean[16]; - - W_CleanupName (name, clean); - - for (lump_p=wad_lumps, i=0 ; iname)) - return lump_p; - } - - Sys_Error ("W_GetLumpinfo: %s not found", name); - return NULL; -}*/ -void *W_SafeGetLumpName (const char *name, size_t *size) -{ - int i; - lumpinfo_t *lump_p; - char clean[16]; + *type = 0; + *size = 0; W_CleanupName (name, clean); @@ -171,6 +156,7 @@ void *W_SafeGetLumpName (const char *name, size_t *size) { if (!strcmp(clean, lump_p->name)) { + *type = lump_p->type; *size = lump_p->disksize; return (void *)(wad_base+lump_p->filepos); } @@ -178,27 +164,6 @@ void *W_SafeGetLumpName (const char *name, size_t *size) return NULL; } -/*void *W_GetLumpName (char *name) -{ - lumpinfo_t *lump; - - lump = W_GetLumpinfo (name); - - return (void *)(wad_base + lump->filepos); -}*/ - -/*void *W_GetLumpNum (int num) -{ - lumpinfo_t *lump; - - if (num < 0 || num >= wad_numlumps) - Sys_Error ("W_GetLumpNum: bad number: %i", num); - - lump = wad_lumps + num; - - return (void *)(wad_base + lump->filepos); -}*/ - /* ============================================================================= @@ -499,10 +464,11 @@ qbyte *W_GetTexture(const char *name, int *width, int *height, qboolean *usesalp { qpic_t *p; size_t lumpsize; - p = W_SafeGetLumpName(name+4, &lumpsize); + qbyte lumptype; + p = W_GetLumpName(name+4, &lumpsize, &lumptype); if (p) { - if (!strcmp(name+4, "conchars") && lumpsize==128*128) + if (/*lumptype == TYP_QPIC && */!strcmp(name+4, "conchars") && lumpsize==128*128) { //conchars has no header. qbyte *lump = (qbyte*)p; extern cvar_t con_ocranaleds; @@ -529,7 +495,7 @@ qbyte *W_GetTexture(const char *name, int *width, int *height, qboolean *usesalp return data; } - else if (lumpsize == 8+p->width*p->height) + else if (lumptype == TYP_QPIC && lumpsize == 8+p->width*p->height) { *width = p->width; *height = p->height; @@ -542,6 +508,26 @@ qbyte *W_GetTexture(const char *name, int *width, int *height, qboolean *usesalp } return data; } + else if (lumptype == TYP_QPIC && lumpsize == 8+p->width*p->height+4+768) + { //halflife, 24bit palette at end + qbyte *pal = p->data+p->width*p->height+4; + *width = p->width; + *height = p->height; + *usesalpha = true; + + data = BZ_Malloc(p->width * p->height * 4); + for (i = 0; i < p->width * p->height; i++) + { + qbyte *rgb = pal + p->data[i]*3; + data[i*4+0] = rgb[0]; + data[i*4+1] = rgb[1]; + data[i*4+2] = rgb[2]; + data[i*4+3] = ((p->data[i]==255)?0:255); + } + return data; + } + else + Con_Printf("W_GetTexture: unknown lump type\n"); } } diff --git a/engine/client/wad.h b/engine/client/wad.h index d6b3ba94..02675130 100644 --- a/engine/client/wad.h +++ b/engine/client/wad.h @@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define TYP_QPIC 66 #define TYP_SOUND 67 #define TYP_MIPTEX 68 +#define TYP_HLFONT 70 //on disk representation of most q1 images. typedef struct @@ -91,8 +92,7 @@ void W_Shutdown (void); void W_LoadWadFile (char *filename); void W_CleanupName (const char *in, char *out); //lumpinfo_t *W_GetLumpinfo (char *name); -//void *W_GetLumpName (char *name); -void *W_SafeGetLumpName (const char *name, size_t *size); +void *W_GetLumpName (const char *name, size_t *size, qbyte *lumptype); //void *W_GetLumpNum (int num); void Wads_Flush (void); extern void *wadmutex; diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index c1c902b1..44e03b9e 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -1376,7 +1376,7 @@ TP_ParseFunChars Doesn't check for overflows, so strlen(s) should be < MAX_MACRO_STRING ============== */ -static char *TP_ParseFunChars (char *s) +char *TP_ParseFunChars (char *s) { static char buf[MAX_MACRO_STRING]; char *out = buf; diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 20d31c4c..2fc49203 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -21,6 +21,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "fs.h" +#ifndef SERVERONLY +#include "cl_master.h" +#endif cvar_t ruleset_allow_in = CVAR("ruleset_allow_in", "1"); cvar_t rcon_level = CVAR("rcon_level", "20"); @@ -765,6 +768,37 @@ void Cmd_Exec_f (void) if (fs_manifest->defaultoverrides) Cbuf_InsertText (fs_manifest->defaultoverrides, level, false); } +#ifndef QUAKETC + //hack to try to work around nquake's b0rkedness + if (!strncmp(s, "// ", 3)) + { + char *eol = strstr(s, "\n"); + if (eol) + { + *eol = 0; + s = eol+1; + if (strstr(f, "nQuake")) + { //this is evil, but if we're running quake then com_parseutf8 will be 0 and we can just convert to quake chars. + char *in = s; + char *out = s; + int foundone = 0; + while (*in) + { + if (*in == '^') + { + *out++ = 0x80|*++in; + foundone++; + } + else + *out++ = *in; + in++; + } + if (foundone) + Cbuf_InsertText(va("echo fixups for nquake config %s: %i replacements\n", buf, foundone), level, false); + } + } + } +#endif Cbuf_InsertText (s, level, true); if (cvar_watched) Cbuf_InsertText (va("echo BEGIN %s", buf), level, true); @@ -794,21 +828,32 @@ Cmd_Echo_f Just prints the rest of the line to the console =============== */ +char *TP_ParseFunChars (char *s); void Cmd_Echo_f (void) { + char text[4096]; + char extext[4096], *t; + int level = Cmd_ExecLevel; int i; + *text = 0; for (i=1 ; i= 2) - Con_Printf (" "); -#ifdef SERVERONLY - Con_Printf ("%s", Cmd_Argv(i)); -#else - Con_PrintFlags (Cmd_Argv(i), (com_parseezquake.ival?PFS_EZQUAKEMARKUP:0), 0); -#endif + Q_strncatz(text, " ", sizeof(text)); + Q_strncatz(text, Cmd_Argv(i), sizeof(text)); } - Con_Printf ("\n"); + Q_strncatz(text, "\n", sizeof(text)); + + //echo text is often quoted, so expand the text again now that we're no longer in quotes. + t = Cmd_ExpandString(text, extext, sizeof(extext), &level, !Cmd_IsInsecure()?true:false, true); + +#ifdef SERVERONLY + Con_Printf ("%s", t); +#else + t = TP_ParseFunChars(t); + Con_PrintFlags (t, (com_parseezquake.ival?PFS_EZQUAKEMARKUP:0), 0); +#endif } static void Key_Alias_c(int argn, const char *partial, struct xcommandargcompletioncb_s *ctx) @@ -3756,6 +3801,10 @@ void Cmd_WriteConfig_f(void) snprintf(fname, sizeof(fname), "fte.cfg"); #endif +#ifndef SERVERONLY + MasterInfo_WriteServers(); +#endif + f = FS_OpenWithFriends(fname, sysname, sizeof(sysname), 3, "quake.rc", "hexen.rc", "*.cfg", "configs/*.cfg"); all = cfg_save_all.ival; diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index c0311ac1..94125292 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -727,7 +727,7 @@ struct #ifndef SERVERONLY #ifdef D3DQUAKE -void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t *colours, int vertcount, vec3_t *normals) +void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t *colours, int vertcount, vec3_t *normals, qboolean usecolourmod) { int i; int c; @@ -745,7 +745,7 @@ void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t * shadelightb[i] = bound(0, l, 255); } - if (ambientlightb[0] == shadelightb[0] && ambientlightb[1] == shadelightb[1] && ambientlightb[2] == shadelightb[2]) + if (!normals || (ambientlightb[0] == shadelightb[0] && ambientlightb[1] == shadelightb[1] && ambientlightb[2] == shadelightb[2])) { for (i = vertcount-1; i >= 0; i--) { @@ -774,7 +774,7 @@ void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t * } #endif -void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *normals, float scale) +void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int vertcount, vec3_t *normals, float scale, qboolean colormod) { extern cvar_t r_vertexdlights; int i; @@ -782,20 +782,28 @@ void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int //float *lightdir = currententity->light_dir; //unused variable - if (!entity->light_range[0] && !entity->light_range[1] && !entity->light_range[2]) + if (!normals || (!entity->light_range[0] && !entity->light_range[1] && !entity->light_range[2])) { + vec3_t val; + VectorCopy(entity->light_avg, val); + if (colormod) + VectorMul(val, entity->shaderRGBAf, val); + for (i = vertcount-1; i >= 0; i--) { - colours[i][0] = entity->light_avg[0]; - colours[i][1] = entity->light_avg[1]; - colours[i][2] = entity->light_avg[2]; + VectorCopy(val, colours[i]); } } else { - vec3_t la, lr; + avec3_t la, lr; VectorScale(entity->light_avg, scale, la); VectorScale(entity->light_range, scale, lr); + if (colormod) + { + VectorMul(la, entity->shaderRGBAf, la); + VectorMul(lr, entity->shaderRGBAf, lr); + } #ifdef SSE_INTRINSICS __m128 va, vs, vl, vr; va = _mm_load_ps(ambientlight); @@ -822,7 +830,7 @@ void R_LightArrays(const entity_t *entity, vecV_t *coords, avec4_t *colours, int } } - if (r_vertexdlights.ival && r_dynamic.ival > 0) + if (r_vertexdlights.ival && r_dynamic.ival > 0 && normals) { unsigned int lno, v; vec3_t dir, rel; diff --git a/engine/common/com_phys_ode.c b/engine/common/com_phys_ode.c index f5adff9f..a043a1a8 100644 --- a/engine/common/com_phys_ode.c +++ b/engine/common/com_phys_ode.c @@ -1696,8 +1696,6 @@ static void World_ODE_Frame_JointFromEntity(world_t *world, wedict_t *ed) default: break; } -#undef SETPARAMS - } } diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index 3a70917f..ae0d427c 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -69,6 +69,7 @@ extern vec3_t vec3_origin; #define VectorAdd(a,b,c) do{(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];}while(0) #define VectorCopy(a,b) do{(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];}while(0) #define VectorScale(a,s,b) do{(b)[0]=(s)*(a)[0];(b)[1]=(s)*(a)[1];(b)[2]=(s)*(a)[2];}while(0) +#define VectorMul(a,s,b) do{(b)[0]=(s)[0]*(a)[0];(b)[1]=(s)[1]*(a)[1];(b)[2]=(s)[2]*(a)[2];}while(0) #define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0) #define VectorSet(r,x,y,z) do{(r)[0] = x; (r)[1] = y;(r)[2] = z;}while(0) #define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2]) diff --git a/engine/d3d/d3d11_backend.c b/engine/d3d/d3d11_backend.c index b42f8e83..0fd441ed 100644 --- a/engine/d3d/d3d11_backend.c +++ b/engine/d3d/d3d11_backend.c @@ -1268,7 +1268,7 @@ static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *srcb, } else { - R_LightArraysByte_BGR(shaderstate.curentity , mesh->xyz_array, dst, cnt, mesh->normals_array); + R_LightArraysByte_BGR(shaderstate.curentity , mesh->xyz_array, dst, cnt, mesh->normals_array, pass->rgbgen==RGB_GEN_ENTITY_LIGHTING_DIFFUSE); } break; case RGB_GEN_WAVE: diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index 3b8aa7d8..733fe566 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -1021,20 +1021,11 @@ static void colourgenbyte(const shaderpass_t *pass, int cnt, byte_vec4_t *srcb, ((D3DCOLOR*)dst)[cnt] = block; } break; + case RGB_GEN_ENTITY_LIGHTING_DIFFUSE: + R_LightArraysByte_BGR(shaderstate.curentity , mesh->xyz_array, dst, cnt, mesh->normals_array, true); + break; case RGB_GEN_LIGHTING_DIFFUSE: - //collect lighting details for mobile entities - if (!mesh->normals_array) - { - block = D3DCOLOR_RGBA(255, 255, 255, 255); - while((cnt)--) - { - ((D3DCOLOR*)dst)[cnt] = block; - } - } - else - { - R_LightArraysByte_BGR(shaderstate.curentity , mesh->xyz_array, dst, cnt, mesh->normals_array); - } + R_LightArraysByte_BGR(shaderstate.curentity , mesh->xyz_array, dst, cnt, mesh->normals_array, false); break; case RGB_GEN_WAVE: { @@ -1987,6 +1978,9 @@ static void BE_ApplyUniforms(program_t *prog, int permu) case SP_W_FOG: IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, r_refdef.globalfog.colour, 2); //colour and density break; + case SP_W_USER://FIXME: needs seperate vertex+fragment handles! + IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, r_refdef.userdata[0], countof(r_refdef.userdata)); + break; case SP_M_ENTBONES: case SP_M_MODELVIEW: diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 44d1a79c..2269742b 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -2084,21 +2084,11 @@ static void colourgen(const shaderpass_t *pass, int cnt, vec4_t *src, vec4_t *ds dst[cnt][2] = pass->rgbgen_func.args[2]; } break; + case RGB_GEN_ENTITY_LIGHTING_DIFFUSE: + R_LightArrays(shaderstate.curentity, mesh->xyz_array, dst, cnt, mesh->normals_array, shaderstate.identitylighting, true); + break; case RGB_GEN_LIGHTING_DIFFUSE: - //collect lighting details for mobile entities - if (!mesh->normals_array) - { - while((cnt)--) - { - dst[cnt][0] = 1; - dst[cnt][1] = 1; - dst[cnt][2] = 1; - } - } - else - { - R_LightArrays(shaderstate.curentity, mesh->xyz_array, dst, cnt, mesh->normals_array, shaderstate.identitylighting); - } + R_LightArrays(shaderstate.curentity, mesh->xyz_array, dst, cnt, mesh->normals_array, shaderstate.identitylighting, false); break; case RGB_GEN_WAVE: { @@ -2572,7 +2562,7 @@ static void GenerateColourMods(const shaderpass_t *pass) else { extern cvar_t r_nolightdir; - if (pass->rgbgen == RGB_GEN_LIGHTING_DIFFUSE) + if (pass->rgbgen == RGB_GEN_LIGHTING_DIFFUSE || pass->rgbgen == RGB_GEN_ENTITY_LIGHTING_DIFFUSE) { if (shaderstate.mode == BEM_DEPTHDARK || shaderstate.mode == BEM_DEPTHONLY) { @@ -3466,7 +3456,7 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm, qglUniform4fvARB(ph, 2, r_refdef.globalfog.colour); //and density break; case SP_W_USER: - qglUniform4fvARB(ph, countof(r_refdef.userdata), r_refdef.userdata); //and density + qglUniform4fvARB(ph, countof(r_refdef.userdata), r_refdef.userdata[0]); //and density break; case SP_V_EYEPOS: qglUniform3fvARB(ph, 1, r_origin); @@ -4022,7 +4012,7 @@ static void BE_LegacyLighting(void) } } - if (TEXVALID(shaderstate.curtexnums->bump) && gl_config.arb_texture_cube_map && gl_config.arb_texture_env_dot3 && gl_config.arb_texture_env_combine && be_maxpasses >= 4) + if (TEXLOADED(shaderstate.curtexnums->bump) && gl_config.arb_texture_cube_map && gl_config.arb_texture_env_dot3 && gl_config.arb_texture_env_combine && be_maxpasses >= 4) { //we could get this down to 2 tmus by arranging for the dot3 result to be written the alpha buffer. But then we'd need to have an alpha buffer too. if (!shaderstate.normalisationcubemap) @@ -4056,7 +4046,7 @@ static void BE_LegacyLighting(void) tmu++; //tmu3: $any+multiply-by-colour+notc - GL_LazyBind(tmu, GL_TEXTURE_2D, shaderstate.curtexnums->bump); //texture not used, its just to make sure the code leaves it enabled. + GL_LazyBind(tmu, GL_TEXTURE_2D, shaderstate.curtexnums->base); //texture not used, its just to make sure the code leaves it enabled. BE_SetPassBlendMode(tmu, PBM_MODULATE_PREV_COLOUR); shaderstate.pendingtexcoordparts[tmu] = 0; shaderstate.pendingtexcoordvbo[tmu] = 0; @@ -4098,9 +4088,9 @@ static void BE_LegacyLighting(void) BE_SubmitMeshChain(false); - GL_LazyBind(1, 0, r_nulltex); - GL_LazyBind(2, 0, r_nulltex); - GL_LazyBind(3, 0, r_nulltex); +// GL_LazyBind(1, 0, r_nulltex); +// GL_LazyBind(2, 0, r_nulltex); +// GL_LazyBind(3, 0, r_nulltex); } #endif diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 3f0b0c5a..9237b8ff 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -67,6 +67,7 @@ typedef unsigned int FT_Pixel_Mode; //for consistency even without freetype supp #define FT_PIXEL_MODE_BGRA 7 //added in FT 2.5 #endif #define FT_PIXEL_MODE_RGBA_SA (~(FT_Pixel_Mode)0) //RGBA, straight alpha. not in freetype. +#define FT_PIXEL_MODE_RGBA (~(FT_Pixel_Mode)1) //RGBA, premultiplied alpha. not in freetype. static const char *imgs[] = { @@ -193,25 +194,60 @@ static const char *imgs[] = #define PLANEWIDTH FIMAGEWIDTH #define PLANEHEIGHT FIMAGEHEIGHT -#ifdef AVAIL_FREETYPE //windows' font linking allows linking multiple extra fonts to a main font. //this means that a single selected font can use chars from lots of different files if the first one(s) didn't provide that font. //they're provided as fallbacks. -#define MAX_FTFACES 32 +#define MAX_FACES 32 -typedef struct ftfontface_s +typedef struct fontface_s { - struct ftfontface_s *fnext; - struct ftfontface_s **flink; //like prev, but not. + struct fontface_s *fnext; + struct fontface_s **flink; //like prev, but not. char name[MAX_OSPATH]; int refs; - int activeheight; //needs reconfiguring when different sizes are used - FT_Face face; - void *membuf; -} ftfontface_t; -static ftfontface_t *ftfaces; + + struct + { + qbyte *data; + size_t width; + size_t height; + } horiz; + +#ifdef HALFLIFEMODELS + struct + { + int fontheight1; + int imgheight; + int rows; + int fontheight2; + + struct + { + qbyte x; + qbyte y; + qbyte width; + qbyte pad; + } chartab[256]; + +// int unk[4]; + + qbyte data[1];//[256*imgheight]; + //int pad + //palette[256*3]; + } *halflife; #endif +#ifdef AVAIL_FREETYPE + struct + { + int activeheight; //needs reconfiguring when different sizes are used + FT_Face face; + void *membuf; + } ft; +#endif +} fontface_t; +static fontface_t *faces; + #define GEN_CONCHAR_GLYPHS 0 //set to 0 or 1 to define whether to generate glyphs from conchars too, or if it should just draw them as glquake always used to extern cvar_t cl_noblink; @@ -241,13 +277,12 @@ typedef struct font_s } *chars[FONTBLOCKS]; char name[MAX_OSPATH]; - short charheight; texid_t singletexture; -#ifdef AVAIL_FREETYPE - //FIXME: multiple sized font_t objects should refer to a single FT_Face. - int ftfaces; - ftfontface_t *face[MAX_FTFACES]; -#endif + unsigned short charheight; + + unsigned short faces; + fontface_t *face[MAX_FACES]; + struct font_s *alt; vec3_t tint; vec3_t alttint; @@ -398,7 +433,7 @@ void Font_Init(void) "map $diffuse\n" "rgbgen vertex\n" "alphagen vertex\n" - "blendfunc blend\n" + "blendfunc gl_one gl_one_minus_src_alpha\n" "}\n" "}\n" ); @@ -410,7 +445,7 @@ void Font_Init(void) "map $whiteimage\n" "rgbgen vertex\n" "alphagen vertex\n" - "blendfunc blend\n" + "blendfunc gl_one gl_one_minus_src_alpha\n" "}\n" "}\n" ); @@ -602,7 +637,33 @@ static struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, FT { //8bit font for (y = -pad; y < 0; y++) { - for (x = -pad; x < bmw+pad; x++) + for (x = -pad; x < (int)bmw+pad; x++) + *(unsigned int *)&out[x*4] = BORDERCOLOUR; + out += PLANEWIDTH*4; + } + for (; y < bmh; y++) + { + for (x = -pad; x < 0; x++) + *(unsigned int *)&out[x*4] = BORDERCOLOUR; + for (; x < bmw; x++) + *(unsigned int *)&out[x*4] = 0x01010101 * ((unsigned char*)data)[x]; + for (; x < bmw+pad; x++) + *(unsigned int *)&out[x*4] = BORDERCOLOUR; + data = (char*)data + pitch; + out += PLANEWIDTH*4; + } + for (; y < bmh+pad; y++) + { + for (x = -pad; x < (int)bmw+pad; x++) + *(unsigned int *)&out[x*4] = BORDERCOLOUR; + out += PLANEWIDTH*4; + } + } + else if (pixelmode == FT_PIXEL_MODE_RGBA_SA) + { //rgba font + for (y = -pad; y < 0; y++) + { + for (x = -pad; x < (int)bmw+pad; x++) *(unsigned int *)&out[x*4] = BORDERCOLOUR; out += PLANEWIDTH*4; } @@ -612,44 +673,24 @@ static struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, FT *(unsigned int *)&out[x*4] = BORDERCOLOUR; for (; x < bmw; x++) { - *(unsigned int *)&out[x*4] = 0xffffffff; - out[x*4+3] = ((unsigned char*)data)[x]; + if (((unsigned char*)data)[x*4+3] == 255) + ((unsigned int*)out)[x] = ((unsigned int*)data)[x]; + else + { + out[x*4+0] = (((unsigned char*)data)[x*4+3]*((unsigned char*)data)[x*4+0])<<8; + out[x*4+1] = (((unsigned char*)data)[x*4+3]*((unsigned char*)data)[x*4+1])<<8; + out[x*4+2] = (((unsigned char*)data)[x*4+3]*((unsigned char*)data)[x*4+2])<<8; + out[x*4+3] = ((unsigned char*)data)[x*4+3]; + } } for (; x < bmw+pad; x++) *(unsigned int *)&out[x*4] = BORDERCOLOUR; data = (char*)data + pitch; out += PLANEWIDTH*4; } - for (; y < bmh+pad; y++) + for (; y < (int)bmh+pad; y++) { - for (x = -pad; x < bmw+pad; x++) - *(unsigned int *)&out[x*4] = BORDERCOLOUR; - out += PLANEWIDTH*4; - } - } - else if (pixelmode == FT_PIXEL_MODE_RGBA_SA) - { //rgba font - pitch*=4; - for (y = -pad; y < 0; y++) - { - for (x = -pad; x < bmw+pad; x++) - *(unsigned int *)&out[x*4] = BORDERCOLOUR; - out += PLANEWIDTH*4; - } - for (; y < bmh; y++) - { - for (x = -pad; x < 0; x++) - *(unsigned int *)&out[x*4] = BORDERCOLOUR; - for (; x < bmw; x++) - ((unsigned int*)out)[x] = ((unsigned int*)data)[x]; - for (; x < bmw+pad; x++) - *(unsigned int *)&out[x*4] = BORDERCOLOUR; - data = (char*)data + pitch; - out += PLANEWIDTH*4; - } - for (; y < bmh+pad; y++) - { - for (x = -pad; x < bmw+pad; x++) + for (x = -pad; x < (int)bmw+pad; x++) *(unsigned int *)&out[x*4] = BORDERCOLOUR; out += PLANEWIDTH*4; } @@ -658,7 +699,7 @@ static struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, FT { //bgra srgb font, already premultiplied for (y = -pad; y < 0; y++) { - for (x = -pad; x < bmw+pad; x++) + for (x = -pad; x < (int)bmw+pad; x++) *(unsigned int *)&out[x*4] = BORDERCOLOUR; out += PLANEWIDTH*4; } @@ -680,7 +721,33 @@ static struct charcache_s *Font_LoadGlyphData(font_t *f, CHARIDXTYPE charidx, FT } for (; y < bmh+pad; y++) { - for (x = -pad; x < bmw+pad; x++) + for (x = -pad; x < (int)bmw+pad; x++) + *(unsigned int *)&out[x*4] = BORDERCOLOUR; + out += PLANEWIDTH*4; + } + } + else if (pixelmode == FT_PIXEL_MODE_RGBA) + { //bgra srgb font, already premultiplied + for (y = -pad; y < 0; y++) + { + for (x = -pad; x < (int)bmw+pad; x++) + *(unsigned int *)&out[x*4] = BORDERCOLOUR; + out += PLANEWIDTH*4; + } + for (; y < bmh; y++) + { + for (x = -pad; x < 0; x++) + *(unsigned int *)&out[x*4] = BORDERCOLOUR; + for (; x < bmw; x++) + ((unsigned int*)out)[x] = ((unsigned int*)data)[x]; + for (; x < bmw+pad; x++) + *(unsigned int *)&out[x*4] = BORDERCOLOUR; + data = (char*)data + pitch; + out += PLANEWIDTH*4; + } + for (; y < bmh+pad; y++) + { + for (x = -pad; x < (int)bmw+pad; x++) *(unsigned int *)&out[x*4] = BORDERCOLOUR; out += PLANEWIDTH*4; } @@ -770,7 +837,7 @@ static struct charcache_s *Font_LoadPlaceholderGlyph(font_t *f, CHARIDXTYPE char if (g & 1) out[o+2] = 0xff0000ff; } } - c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA_SA, out, w, h, w); + c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA, out, w, h, w*4); if (c) { c->advance = w+1; @@ -815,7 +882,7 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx) } s+=128; } - c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA_SA, img, 8*scale, 8*scale, 8*scale); + c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA_SA, img, 8*scale, 8*scale, 8*scale*4); if (c) { c->advance = 8*scale; @@ -831,6 +898,7 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx) if (charidx >= 0xe100 && charidx <= 0xe1ff) { qpic_t *wadimg; + qbyte lumptype = 0; unsigned char *src; unsigned int img[64*64]; int nw, nh; @@ -842,8 +910,8 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx) if (charidx-0xe100 >= sizeof(imgs)/sizeof(imgs[0])) wadimg = NULL; else - wadimg = W_SafeGetLumpName(imgs[charidx-0xe100], &lumpsize); - if (wadimg && lumpsize == 8+wadimg->height*wadimg->width) + wadimg = W_GetLumpName(imgs[charidx-0xe100], &lumpsize, &lumptype); + if (wadimg && lumptype == TYP_QPIC && lumpsize == 8+wadimg->height*wadimg->width) { nh = wadimg->height; nw = wadimg->width; @@ -877,7 +945,7 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx) } } - c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA_SA, img, nw, nh, 64); + c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA_SA, img, nw, nh, 64*4); if (c) { c->left = 0; @@ -903,60 +971,180 @@ static struct charcache_s *Font_TryLoadGlyph(font_t *f, CHARIDXTYPE charidx) return c; } -#ifdef AVAIL_FREETYPE - if (f->ftfaces) + if (f->faces) { int file; - for (file = 0; file < f->ftfaces; file++) + for (file = 0; file < f->faces; file++) { - FT_Face face = f->face[file]->face; + fontface_t *qface = f->face[file]; +#ifdef AVAIL_FREETYPE + if (qface->ft.face) + { + FT_Face face = qface->ft.face; -// if (f->face[file]->activeheight) - if (f->face[file]->activeheight != f->charheight) - { - f->face[file]->activeheight = f->charheight; -// if (FT_HAS_FIXED_SIZES(face)) -// pFT_Select_Size(face, 0); -// else - pFT_Set_Pixel_Sizes(face, 0, f->charheight); - } - if (charidx == 0xfffe || pFT_Get_Char_Index(face, charidx)) //ignore glyph 0 (undefined) - if (pFT_Load_Char(face, charidx, FT_LOAD_RENDER|FT_LOAD_COLOR) == 0) - { - FT_GlyphSlot slot; - FT_Bitmap *bm; - - slot = face->glyph; - bm = &slot->bitmap; - if (!f->face[file]->activeheight && bm->pixel_mode == FT_PIXEL_MODE_BGRA) +// if (qface->activeheight) + if (qface->ft.activeheight != f->charheight) { - unsigned int *out = alloca(f->charheight*f->charheight*4); - Image_ResampleTexture((void*)bm->buffer, bm->width, bm->rows, out, f->charheight, f->charheight); - c = Font_LoadGlyphData(f, charidx, bm->pixel_mode, out, f->charheight, f->charheight, f->charheight*4); - if (c) + qface->ft.activeheight = f->charheight; +// if (FT_HAS_FIXED_SIZES(face)) +// pFT_Select_Size(face, 0); +// else + pFT_Set_Pixel_Sizes(face, 0, f->charheight); + } + if (charidx == 0xfffe || pFT_Get_Char_Index(face, charidx)) //ignore glyph 0 (undefined) + if (pFT_Load_Char(face, charidx, FT_LOAD_RENDER|FT_LOAD_COLOR) == 0) + { + FT_GlyphSlot slot; + FT_Bitmap *bm; + + slot = face->glyph; + bm = &slot->bitmap; + if (!qface->ft.activeheight && bm->pixel_mode == FT_PIXEL_MODE_BGRA) { - c->advance = f->charheight; - c->left = 0; - c->top = 0; - return c; + unsigned int *out = alloca(f->charheight*f->charheight*4); + Image_ResampleTexture((void*)bm->buffer, bm->width, bm->rows, out, f->charheight, f->charheight); + c = Font_LoadGlyphData(f, charidx, bm->pixel_mode, out, f->charheight, f->charheight, f->charheight*4); + if (c) + { + c->advance = f->charheight; + c->left = 0; + c->top = 0; + return c; + } } + else + { + c = Font_LoadGlyphData(f, charidx, bm->pixel_mode, bm->buffer, bm->width, bm->rows, bm->pitch); + + if (c) + { + c->advance = slot->advance.x >> 6; + c->left = slot->bitmap_left; + c->top = f->charheight*3/4 - slot->bitmap_top; + return c; + } + } + } + } + else +#endif +#ifdef HALFLIFEMODELS + if (qface->halflife) + { + size_t glyph = charidx; + if (glyph > 0xe000) + glyph -= 0xe000; + if (glyph < 0x100) + { + int gw = qface->halflife->chartab[glyph].width; + int gh = qface->halflife->fontheight1; + qbyte *in = qface->halflife->data + 256 * qface->halflife->chartab[glyph].y + qface->halflife->chartab[glyph].x; + qbyte *pal = qface->halflife->data + 256 * qface->halflife->imgheight+2; + qbyte *out = alloca(gw*gh*4); + int x, y; + for (y = 0; y < gh; y++, in += 256-gw) + for (x = 0; x < gw; x++, in++) + { + if (*in==0xff) + { + out[(x+y*gw)*4+0] = 0; + out[(x+y*gw)*4+1] = 0; + out[(x+y*gw)*4+2] = 0; + out[(x+y*gw)*4+3] = 0; + } + else + { + out[(x+y*gw)*4+0] = pal[*in*3+0]; + out[(x+y*gw)*4+1] = pal[*in*3+1]; + out[(x+y*gw)*4+2] = pal[*in*3+2]; + out[(x+y*gw)*4+3] = 0xff; + } + } + + if (f->charheight != gh) + { + int ngw = (gw * f->charheight) / gh; + int ngh = f->charheight; + qbyte *out2 = alloca(ngw*ngh*4); + if (ngw&&ngh) + Image_ResampleTexture((unsigned int *)out, gw, gh, (unsigned int *)out2, ngw, ngh); + c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA, out2, ngw, ngh, ngw*4); + gw = ngw; } else + c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA, out, gw, gh, gw*4); + if (c) { - c = Font_LoadGlyphData(f, charidx, bm->pixel_mode, bm->buffer, bm->width, bm->rows, bm->pitch); - - if (c) - { - c->advance = slot->advance.x >> 6; - c->left = slot->bitmap_left; - c->top = f->charheight*3/4 - slot->bitmap_top; - return c; - } + c->advance = gw; + c->left = 0; + c->top = 0; + return c; } } + } + else +#endif + if (qface->horiz.data) + { +#if 1 + size_t maxchar = 256; + int gw = qface->horiz.width/maxchar; +#else + int gw = qface->horiz.height-(qface->horiz.height/12); + size_t maxchar = qface->horiz.width / gw; +#endif + size_t glyph = charidx /* - qface->horiz.firstcodepoint*/; + if (glyph < maxchar) + { + unsigned int *glyphdata = (unsigned int*)qface->horiz.data + glyph*gw; + int gh = qface->horiz.height; + int gs = qface->horiz.width; + unsigned int *out = glyphdata; + while (gw >= 1) + { + int y; + gw--; //see if we can strip this column + for (y = 0; y < gh; y++) + if (glyphdata[gw+y*gs] & 0x00ffffff) + break; + if (y < gh) + { + gw++; + break; + } + } + if (f->charheight != gh) + { + int ngw = (gw * f->charheight) / gh; + int ngh = f->charheight; + int x, y; + unsigned int *out2 = alloca(ngw*ngh*4); + if (ngw&&ngh) + { //we need to repack the input, because Image_ResampleTexture can't handle strides + unsigned int *out1 = alloca(gw*gh*4); + for (y = 0; y < gh; y++) + for (x = 0; x < gw; x++) + out1[x+y*gw] = out[x+y*gs]; + Image_ResampleTexture((unsigned int *)out1, gw, gh, (unsigned int *)out2, ngw, ngh); + } + c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA, out2, ngw, ngh, ngw*4); + gw = ngw; + } + else + c = Font_LoadGlyphData(f, charidx, FT_PIXEL_MODE_RGBA, out, gw, gh, gs*4); + if (!gw) //for invisble glyphs (eg: space), we attempt to ensure that there's some substance there. missing spaces is weird. + gw = gh/3; + if (c) + { + c->advance = gw; + c->left = 0; + c->top = 0; + return c; + } + } + } } } -#endif if (charidx == '\r') return Font_CopyChar(f, charidx|0xe000, charidx); @@ -1032,10 +1220,62 @@ static struct charcache_s *Font_GetChar(font_t *f, unsigned int codepoint) return c; } +qboolean Font_LoadHorizontalFont(struct font_s *f, int fheight, const char *fontfilename) +{ //halflife-style. + fontface_t *qface; + void *rawdata; + qofs_t rawsize; + qbyte *rgbadata = NULL; + int width=0,height=0; + qboolean hasalpha=true; + + if (fheight < 1) + fheight = 1; + + //ran out of font slots. + if (f->faces == MAX_FACES) + return false; + + for (qface = faces; qface; qface = qface->fnext) + { + if (!strcmp(qface->name, fontfilename) && qface->horiz.data) + { + qface->refs++; + f->face[f->faces++] = qface; + return true; + } + } + + rawdata = FS_MallocFile(fontfilename, FS_GAME, &rawsize); + if (rawdata) + rgbadata = Read32BitImageFile(rawdata, rawsize, &width, &height, &hasalpha, fontfilename); + FS_FreeFile(rawdata); + + if (rgbadata) + { + /*success!*/ + qface = Z_Malloc(sizeof(*qface)); + qface->flink = &faces; + qface->fnext = *qface->flink; + *qface->flink = qface; + if (qface->fnext) + qface->fnext->flink = &qface->fnext; + qface->horiz.data = rgbadata; + qface->horiz.width = width; + qface->horiz.height = height; + qface->refs++; + Q_strncpyz(qface->name, fontfilename, sizeof(qface->name)); + + f->face[f->faces++] = qface; + return true; + } + return false; +} + +#ifdef AVAIL_FREETYPE qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, const char *fontfilename) { -#ifdef AVAIL_FREETYPE - ftfontface_t *qface; + fontface_t *qface; FT_Face face = NULL; FT_Error error; flocation_t loc; @@ -1047,15 +1287,15 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, const char *fontfil height = 1; //ran out of font slots. - if (f->ftfaces == MAX_FTFACES) + if (f->faces == MAX_FACES) return false; - for (qface = ftfaces; qface; qface = qface->fnext) + for (qface = faces; qface; qface = qface->fnext) { - if (!strcmp(qface->name, fontfilename)) + if (!strcmp(qface->name, fontfilename) && qface->ft.face) { qface->refs++; - f->face[f->ftfaces++] = qface; + f->face[f->faces++] = qface; return true; } } @@ -1184,18 +1424,18 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, const char *fontfil { /*success!*/ qface = Z_Malloc(sizeof(*qface)); - qface->flink = &ftfaces; + qface->flink = &faces; qface->fnext = *qface->flink; *qface->flink = qface; if (qface->fnext) qface->fnext->flink = &qface->fnext; - qface->face = face; - qface->membuf = fbase; + qface->ft.face = face; + qface->ft.activeheight = height; + qface->ft.membuf = fbase; qface->refs++; - qface->activeheight = height; Q_strncpyz(qface->name, fontfilename, sizeof(qface->name)); - f->face[f->ftfaces++] = qface; + f->face[f->faces++] = qface; return true; } } @@ -1203,26 +1443,26 @@ qboolean Font_LoadFreeTypeFont(struct font_s *f, int height, const char *fontfil Con_Printf("Freetype error: %i\n", error); if (fbase) BZ_Free(fbase); -#endif return false; } +#endif static texid_t Font_LoadReplacementConchars(void) { texid_t tex; //q1 replacement - tex = R_LoadHiResTexture("gfx/conchars.lmp", NULL, IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA);//, NULL, 0, 0, TF_INVALID); + tex = R_LoadHiResTexture("gfx/conchars.lmp", NULL, IF_NEAREST|IF_PREMULTIPLYALPHA|IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); TEXDOWAIT(tex); if (TEXLOADED(tex)) return tex; //q2 - tex = R_LoadHiResTexture("pics/conchars.pcx", NULL, IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); + tex = R_LoadHiResTexture("pics/conchars.pcx", NULL, (r_font_linear.ival?IF_LINEAR:IF_NEAREST)|IF_PREMULTIPLYALPHA|IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); TEXDOWAIT(tex); if (TEXLOADED(tex)) return tex; //q3 - tex = R_LoadHiResTexture("gfx/2d/bigchars.tga", NULL, IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); + tex = R_LoadHiResTexture("gfx/2d/bigchars.tga", NULL, (r_font_linear.ival?IF_LINEAR:IF_NEAREST)|IF_PREMULTIPLYALPHA|IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); TEXDOWAIT(tex); if (TEXLOADED(tex)) return tex; @@ -1333,7 +1573,7 @@ static texid_t Font_LoadHexen2Conchars(qboolean iso88591) for (i=0 ; i<128*128 ; i++) if (outbuf[i] == 0) outbuf[i] = 255; // proper transparent color - tex = R_LoadTexture8 (iso88591?"gfx/menu/8859-1.lmp":"charset", 128, 128, outbuf, IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA, 1); + tex = R_LoadTexture8 (iso88591?"gfx/menu/8859-1.lmp":"charset", 128, 128, outbuf, IF_PREMULTIPLYALPHA|IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA, 1); Z_Free(outbuf); return tex; } @@ -1391,7 +1631,7 @@ static texid_t Font_LoadFallbackConchars(void) Font_CopyGlyph(']', 130, lump); Font_CopyGlyph('o', 131, lump); } - tex = R_LoadTexture32("charset", width, height, (void*)lump, IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); + tex = R_LoadTexture32("charset", width, height, (void*)lump, IF_PREMULTIPLYALPHA|IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); BZ_Free(lump); return tex; } @@ -1476,6 +1716,13 @@ struct font_s *Font_LoadFont(float vheight, const char *fontfilename) int height = ((vheight * vid.rotpixelheight)/vid.height) + 0.5; char facename[MAX_QPATH]; struct charcache_s *c; + enum + { + FMT_AUTO, //freetype, or quake + FMT_QUAKE, //first is default + FMT_ISO88591, //latin-1 (first 256 chars of unicode too) + FMT_HORIZONTAL, //unicode, charcount=width/(height-2). single strip of chars, like halflife. + } fmt; Q_strncpy(facename, fontfilename, sizeof(facename)); @@ -1517,8 +1764,19 @@ struct font_s *Font_LoadFont(float vheight, const char *fontfilename) if (*t == ' ') t++; f->tint[2] = strtod(t, &t); parms = t; - } + if (!strncmp(parms, "fmt=", 4)) + { + char *t = parms+4; + fmt = 0; + if (*t == 'q') + fmt = FMT_QUAKE; + else if (*t == 'l') + fmt = FMT_ISO88591; + else if (*t == 'h') + fmt = FMT_HORIZONTAL; + } + while(*parms && *parms != '&') parms++; if (*parms == '&') @@ -1603,7 +1861,8 @@ struct font_s *Font_LoadFont(float vheight, const char *fontfilename) unsigned int *img; int x, y; size_t lumpsize; - unsigned char *w = W_SafeGetLumpName(fontfilename+4, &lumpsize); + qbyte lumptype; + unsigned char *w = W_GetLumpName(fontfilename+4, &lumpsize, &lumptype); if (!w || lumpsize != 5) { Z_Free(f); @@ -1614,7 +1873,7 @@ struct font_s *Font_LoadFont(float vheight, const char *fontfilename) for (x = 0; x < 128; x++) img[x + y*PLANEWIDTH] = w[x + y*128]?d_8to24rgbtable[w[x + y*128]]:0; - f->singletexture = R_LoadTexture("tinyfont",PLANEWIDTH,PLANEWIDTH,TF_RGBA32,img,IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP); + f->singletexture = R_LoadTexture("tinyfont",PLANEWIDTH,PLANEWIDTH,TF_RGBA32,img,IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOPICMIP|IF_NOMIPMAP); if (f->singletexture->status == TEX_LOADING) COM_WorkerPartialSync(f->singletexture, &f->singletexture->status, TEX_LOADING); Z_Free(img); @@ -1689,7 +1948,14 @@ struct font_s *Font_LoadFont(float vheight, const char *fontfilename) char *end = strchr(start, ','); if (end) *end = 0; - Font_LoadFreeTypeFont(f, height, start); + + if (fmt == FMT_HORIZONTAL) + Font_LoadHorizontalFont(f, height, start); +#ifdef AVAIL_FREETYPE + else if (fmt == FMT_AUTO) + Font_LoadFreeTypeFont(f, height, start); +#endif + if (end) { *end = ','; @@ -1700,14 +1966,35 @@ struct font_s *Font_LoadFont(float vheight, const char *fontfilename) } } -#ifdef AVAIL_FREETYPE - if (!f->ftfaces) +#ifdef HALFLIFEMODELS + if (!f->faces) + { + if (f->faces < MAX_FACES) + { + size_t lumpsize; + qbyte lumptype; + void *lumpdata; + lumpdata = W_GetLumpName("conchars", &lumpsize, &lumptype); + if (lumpdata && lumptype == TYP_HLFONT) + { + fontface_t *fa = Z_Malloc(sizeof(*fa)); + fa->halflife = lumpdata; + fa->flink = &fa->fnext; + fa->refs = 1; + f->face[f->faces++] = fa; +// f->charheight = fa->halflife->fontheight1; //force the font to a specific size. + return f; + } + } + } #endif + + if (!f->faces) { //default to only map the ascii-compatible chars from the quake font. if (*fontfilename) { - f->singletexture = R_LoadHiResTexture(fontfilename, "fonts:charsets", IF_UIPIC|IF_NOMIPMAP); + f->singletexture = R_LoadHiResTexture(fontfilename, "fonts:charsets", IF_PREMULTIPLYALPHA|IF_UIPIC|IF_NOMIPMAP); if (f->singletexture->status == TEX_LOADING) COM_WorkerPartialSync(f->singletexture, &f->singletexture->status, TEX_LOADING); } @@ -1736,12 +2023,8 @@ struct font_s *Font_LoadFont(float vheight, const char *fontfilename) } else*/ { - for ( ; i < 32; i++) - { - // f->chars[i].texplane = INVALIDPLANE; - } /*force it to load, even if there's nothing there*/ - for ( ; i < 128; i++) + for (i = ((fmt==FMT_QUAKE)?32:0); i < ((fmt==FMT_QUAKE)?128:256); i++) { c = Font_GetCharStore(f, i); @@ -1758,11 +2041,18 @@ struct font_s *Font_LoadFont(float vheight, const char *fontfilename) } } - defaultplane = BITMAPPLANE;/*assume the bitmap plane - don't use the fallback as people don't think to use com_parseutf8*/ - if (!TEXLOADED(f->singletexture)) + defaultplane = INVALIDPLANE;/*assume the bitmap plane - don't use the fallback as people don't think to use com_parseutf8*/ + if (TEXLOADED(f->singletexture)) + defaultplane = BITMAPPLANE; + if (TEXLOADED(fontplanes.defaultfont)) + defaultplane = DEFAULTPLANE; + + if (defaultplane == INVALIDPLANE) { if (!TEXLOADED(fontplanes.defaultfont)) + { fontplanes.defaultfont = Font_LoadDefaultConchars(); + } #ifdef HEXEN2 if (!strcmp(fontfilename, "gfx/hexen2")) @@ -1773,21 +2063,29 @@ struct font_s *Font_LoadFont(float vheight, const char *fontfilename) #endif if (!TEXLOADED(f->singletexture)) f->singletexture = fontplanes.defaultfont; + + if (TEXLOADED(f->singletexture)) + defaultplane = BITMAPPLANE; + if (TEXLOADED(fontplanes.defaultfont)) + defaultplane = DEFAULTPLANE; } - /*pack the default chars into it*/ - for (i = 0xe000; i <= 0xe0ff; i++) + if (defaultplane != INVALIDPLANE) { - c = Font_GetCharStore(f, i); - c->advance = f->charheight; - c->bmh = PLANEWIDTH/16; - c->bmw = PLANEWIDTH/16; - c->bmx = ((i&15))*(PLANEWIDTH/16); - c->bmy = ((i&0xf0)/16)*(PLANEWIDTH/16); - c->left = 0; - c->top = 0; - c->nextchar = 0; //these chars are not linked in - c->texplane = defaultplane; + /*pack the default chars into it*/ + for (i = 0xe000; i <= 0xe0ff; i++) + { + c = Font_GetCharStore(f, i); + c->advance = f->charheight; + c->bmh = PLANEWIDTH/16; + c->bmw = PLANEWIDTH/16; + c->bmx = ((i&15))*(PLANEWIDTH/16); + c->bmy = ((i&0xf0)/16)*(PLANEWIDTH/16); + c->left = 0; + c->top = 0; + c->nextchar = 0; //these chars are not linked in + c->texplane = defaultplane; + } } return f; } @@ -1822,24 +2120,24 @@ void Font_Free(struct font_s *f) } } -#ifdef AVAIL_FREETYPE - while(f->ftfaces --> 0) + while(f->faces --> 0) { - ftfontface_t *qface = f->face[f->ftfaces]; + fontface_t *qface = f->face[f->faces]; qface->refs--; if (!qface->refs) { - if (qface->face) - pFT_Done_Face(qface->face); - if (qface->membuf) - BZ_Free(qface->membuf); +#ifdef AVAIL_FREETYPE + if (qface->ft.face) + pFT_Done_Face(qface->ft.face); + if (qface->ft.membuf) + BZ_Free(qface->ft.membuf); +#endif *qface->flink = qface->fnext; if (qface->fnext) qface->fnext->flink = qface->flink; Z_Free(qface); } } -#endif Z_Free(f); } @@ -2139,7 +2437,8 @@ void Font_InvalidateColour(vec4_t newcolour) } font_colourmask = CON_WHITEMASK; - Vector4Copy(newcolour, font_foretint); + VectorScale(newcolour, newcolour[3], font_foretint); + font_foretint[3] = newcolour[3]; Vector4Scale(font_foretint, 255, font_forecolour); font_backcolour[3] = 0; @@ -2237,7 +2536,7 @@ int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint if (charflags & CON_BLINKTEXT) { float a = (sin(realtime*3)+1)*0.4 + 0.2; - rgba[3] *= a; + Vector4Scale(rgba, a, rgba); } font_forecolour[0] = min(rgba[0], 255); font_forecolour[1] = min(rgba[1], 255); @@ -2259,16 +2558,31 @@ int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint font_colourmask = col; col = (charflags&CON_FGMASK)>>CON_FGSHIFT; - rgba[0] = consolecolours[col].fr*255; - rgba[1] = consolecolours[col].fg*255; - rgba[2] = consolecolours[col].fb*255; - rgba[3] = (charflags & CON_HALFALPHA)?0xc0:255; + if(charflags & CON_HALFALPHA) + { + rgba[0] = consolecolours[col].fr*0x7f; + rgba[1] = consolecolours[col].fg*0x7f; + rgba[2] = consolecolours[col].fb*0x7f; + rgba[3] = 0x7f; + } + else + { + rgba[0] = consolecolours[col].fr*255; + rgba[1] = consolecolours[col].fg*255; + rgba[2] = consolecolours[col].fb*255; + rgba[3] = 255; + } col = (charflags&CON_BGMASK)>>CON_BGSHIFT; - font_backcolour[0] = consolecolours[col].fr*255; - font_backcolour[1] = consolecolours[col].fg*255; - font_backcolour[2] = consolecolours[col].fb*255; - font_backcolour[3] = (charflags & CON_NONCLEARBG)?0xc0:0; + if (charflags & CON_NONCLEARBG) + { + font_backcolour[0] = consolecolours[col].fr*255; + font_backcolour[1] = consolecolours[col].fg*255; + font_backcolour[2] = consolecolours[col].fb*255; + font_backcolour[3] = (charflags & CON_NONCLEARBG)?0xc0:0; + } + else + Vector4Set(font_backcolour, 0, 0, 0, 0); if (charflags & CON_2NDCHARSETTEXT) { @@ -2289,7 +2603,7 @@ int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint if (charflags & CON_BLINKTEXT) { float a = (sin(realtime*3)+1)*0.4 + 0.2; - rgba[3] *= a; + Vector4Scale(rgba, a, rgba); } font_forecolour[0] = min(rgba[0], 255); font_forecolour[1] = min(rgba[1], 255); @@ -2504,16 +2818,31 @@ float Font_DrawScaleChar(float px, float py, unsigned int charflags, unsigned in font_colourmask = col; col = (charflags&CON_FGMASK)>>CON_FGSHIFT; - rgba[0] = consolecolours[col].fr*255; - rgba[1] = consolecolours[col].fg*255; - rgba[2] = consolecolours[col].fb*255; - rgba[3] = (charflags & CON_HALFALPHA)?0xc0:255; + if (charflags & CON_HALFALPHA) + { + rgba[0] = consolecolours[col].fr*0x7f; + rgba[1] = consolecolours[col].fg*0x7f; + rgba[2] = consolecolours[col].fb*0x7f; + rgba[3] = 0x7f; + } + else + { + rgba[0] = consolecolours[col].fr*255; + rgba[1] = consolecolours[col].fg*255; + rgba[2] = consolecolours[col].fb*255; + rgba[3] = 255; + } col = (charflags&CON_BGMASK)>>CON_BGSHIFT; - font_backcolour[0] = consolecolours[col].fr*255; - font_backcolour[1] = consolecolours[col].fg*255; - font_backcolour[2] = consolecolours[col].fb*255; - font_backcolour[3] = (charflags & CON_NONCLEARBG)?0xc0:0; + if (charflags & CON_NONCLEARBG) + { + font_backcolour[0] = consolecolours[col].fr*0xc0; + font_backcolour[1] = consolecolours[col].fg*0xc0; + font_backcolour[2] = consolecolours[col].fb*0xc0; + font_backcolour[3] = 0xc0; + } + else + Vector4Set(font_backcolour, 0, 0, 0, 0); if (charflags & CON_2NDCHARSETTEXT) { diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 2207d9be..30dc767f 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -3034,6 +3034,8 @@ static void Shaderpass_RGBGen (shader_t *shader, shaderpass_t *pass, char **ptr) pass->rgbgen = RGB_GEN_ONE_MINUS_VERTEX; else if (!Q_stricmp (token, "lightingDiffuse")) pass->rgbgen = RGB_GEN_LIGHTING_DIFFUSE; + else if (!Q_stricmp (token, "entitylighting")) + pass->rgbgen = RGB_GEN_ENTITY_LIGHTING_DIFFUSE; else if (!Q_stricmp (token, "exactvertex")) pass->rgbgen = RGB_GEN_VERTEX_EXACT; else if (!Q_stricmp (token, "const") || !Q_stricmp (token, "constant")) @@ -4532,7 +4534,7 @@ void Shader_Programify (shader_t *s) for (i = 0; i < s->numpasses; i++) { pass = &s->passes[i]; - if (pass->rgbgen == RGB_GEN_LIGHTING_DIFFUSE) + if (pass->rgbgen == RGB_GEN_LIGHTING_DIFFUSE || pass->rgbgen == RGB_GEN_ENTITY_LIGHTING_DIFFUSE) modellighting = pass; else if (pass->rgbgen == RGB_GEN_ENTITY) modellighting = pass; @@ -6710,6 +6712,7 @@ static char *Shader_DecomposePass(char *o, shaderpass_t *p, qboolean simple) default: case RGB_GEN_IDENTITY: sprintf(o, "RGB_GEN_IDENTITY "); break; case RGB_GEN_CONST: sprintf(o, "RGB_GEN_CONST "); break; + case RGB_GEN_ENTITY_LIGHTING_DIFFUSE: sprintf(o, "RGB_GEN_ENTITY_LIGHTING_DIFFUSE "); break; case RGB_GEN_LIGHTING_DIFFUSE: sprintf(o, "RGB_GEN_LIGHTING_DIFFUSE "); break; case RGB_GEN_WAVE: sprintf(o, "RGB_GEN_WAVE "); break; case RGB_GEN_TOPCOLOR: sprintf(o, "RGB_GEN_TOPCOLOR "); break; diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index c0c3b7d0..574bbe57 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -8415,11 +8415,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" //we need to write specular exponents if we want per-pixel control over that -//#if defined(SPECULAR) +"#if defined(SPECULAR)\n" "ospec = texture2D(s_specular, tc);\n" -//#else -// ospec = vec4(0.0, 0.0, 0.0, 0.0); -//#endif +"#else\n" +"ospec = vec4(0.0, 0.0, 0.0, 0.0);\n" +"#endif\n" "gl_FragColor = vec4(onorm.xyz, ospec.a * FTE_SPECULAR_EXPONENT);\n" "}\n" diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 59f58c36..e7b4808f 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -205,6 +205,7 @@ typedef struct shaderpass_s { RGB_GEN_CONST, RGB_GEN_UNKNOWN, RGB_GEN_LIGHTING_DIFFUSE, + RGB_GEN_ENTITY_LIGHTING_DIFFUSE, RGB_GEN_TOPCOLOR, RGB_GEN_BOTTOMCOLOR } rgbgen; diff --git a/engine/qclib/decomp.c b/engine/qclib/decomp.c index 85ceb5b6..4d2e8988 100644 --- a/engine/qclib/decomp.c +++ b/engine/qclib/decomp.c @@ -1634,14 +1634,11 @@ void DecompileDecompileStatement(dfunction_t * df, dstatement_t * s, int *indent QCC_CatVFile(Decompileofile, ";\n"); } - else if ((OP_MUL_F <= s->op && s->op <= OP_SUB_V) || - (OP_EQ_F <= s->op && s->op <= OP_GT_F) || - (OP_AND_F <= s->op && s->op <= OP_BITOR_F) - /*|| pr_opcodes[s->op].associative == ASSOC_LEFT*/) + else if (pr_opcodes[s->op].flags & OPF_STD) { DecompileOpcode(df, s->a, s->b, s->c, pr_opcodes[s->op].name, typ1, typ2, typ3, true, indent); } - else if (OP_GLOBALADDRESS == s->op) + else if ((pr_opcodes[s->op].flags & OPF_LOADPTR) || OP_GLOBALADDRESS == s->op) { arg1 = DecompileGet(df, s->a, typ1); arg2 = DecompileGet(df, s->b, typ2); @@ -1696,7 +1693,7 @@ void DecompileDecompileStatement(dfunction_t * df, dstatement_t * s, int *indent DecompileImmediate_Insert(df, s->c, line, typ3); } } - else if ((OP_STORE_F <= s->op && s->op <= OP_STORE_FNC) || s->op == OP_STORE_I || s->op == OP_STORE_P) + else if (pr_opcodes[s->op].flags & OPF_STORE) { QCC_type_t *parmtype=NULL; if (s->b >= ofs_parms[0] && s->b < ofs_parms[7]+ofs_size) @@ -1779,7 +1776,7 @@ void DecompileDecompileStatement(dfunction_t * df, dstatement_t * s, int *indent if (arg3) { DecompileIndent(*indent); - QCC_CatVFile(Decompileofile, "%s = %s;\n", arg3, arg1); + QCC_CatVFile(Decompileofile, "%s %s %s;\n", arg3, pr_opcodes[s->op].name, arg1); } else { @@ -1788,23 +1785,27 @@ void DecompileDecompileStatement(dfunction_t * df, dstatement_t * s, int *indent } } - else if (OP_STOREP_F <= s->op && s->op <= OP_STOREP_FNC) + else if (pr_opcodes[s->op].flags & OPF_STOREPTR) { arg1 = DecompileGet(df, s->a, typ2); //FIXME: we need to deal with ref types and other crazyness, so we know whether we need to add * or *& or if we can skip that completely arg2 = DecompileGet(df, s->b, typ2); DecompileIndent(*indent); - QCC_CatVFile(Decompileofile, "%s = %s;\n", arg2, arg1); + QCC_CatVFile(Decompileofile, "%s %s %s;\n", arg2, pr_opcodes[s->op].name, arg1); } else if (OP_CONV_FTOI == s->op) { - arg1 = DecompileGet(df, s->a, typ1); QC_snprintfz(line, sizeof(line), "(int)%s", arg1); DecompileImmediate_Insert(df, s->c, line, type_integer); - + } + else if (OP_CONV_ITOF == s->op) + { + arg1 = DecompileGet(df, s->a, typ1); + QC_snprintfz(line, sizeof(line), "(float)%s", arg1); + DecompileImmediate_Insert(df, s->c, line, type_float); } else if (OP_RAND0 == s->op) { diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index c8032f57..860cfee7 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -190,14 +190,17 @@ typedef struct enum {ASSOC_LEFT, ASSOC_RIGHT, ASSOC_RIGHT_RESULT} associative; struct QCC_type_s **type_a, **type_b, **type_c; - unsigned int flags; + unsigned int flags; //OPF_* //ASSIGNS_B //ASSIGNS_IB //ASSIGNS_C //ASSIGNS_IC } QCC_opcode_t; extern QCC_opcode_t pr_opcodes[]; // sized by initialization - +#define OPF_STD 0x1 //reads a+b, writes c. +#define OPF_STORE 0x2 //b+=a or just b=a +#define OPF_STOREPTR 0x4 //the form of c=(*b+=a) +#define OPF_LOADPTR 0x8 diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 9daf1f29..e53ae356 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -336,113 +336,113 @@ QCC_opcode_t pr_opcodes[] = { {6, "", "DONE", PC_NONE, ASSOC_LEFT, &type_void, &type_void, &type_void}, - {6, "*", "MUL_F", PC_MULDIV, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {6, "*", "MUL_V", PC_MULDIV, ASSOC_LEFT, &type_vector, &type_vector, &type_float}, - {6, "*", "MUL_FV", PC_MULDIV, ASSOC_LEFT, &type_float, &type_vector, &type_vector}, - {6, "*", "MUL_VF", PC_MULDIV, ASSOC_LEFT, &type_vector, &type_float, &type_vector}, + {6, "*", "MUL_F", PC_MULDIV, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {6, "*", "MUL_V", PC_MULDIV, ASSOC_LEFT, &type_vector, &type_vector, &type_float, OPF_STD}, + {6, "*", "MUL_FV", PC_MULDIV, ASSOC_LEFT, &type_float, &type_vector, &type_vector, OPF_STD}, + {6, "*", "MUL_VF", PC_MULDIV, ASSOC_LEFT, &type_vector, &type_float, &type_vector, OPF_STD}, - {6, "/", "DIV_F", PC_MULDIV, ASSOC_LEFT, &type_float, &type_float, &type_float}, + {6, "/", "DIV_F", PC_MULDIV, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, - {6, "+", "ADD_F", PC_ADDSUB, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {6, "+", "ADD_V", PC_ADDSUB, ASSOC_LEFT, &type_vector, &type_vector, &type_vector}, + {6, "+", "ADD_F", PC_ADDSUB, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {6, "+", "ADD_V", PC_ADDSUB, ASSOC_LEFT, &type_vector, &type_vector, &type_vector, OPF_STD}, - {6, "-", "SUB_F", PC_ADDSUB, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {6, "-", "SUB_V", PC_ADDSUB, ASSOC_LEFT, &type_vector, &type_vector, &type_vector}, + {6, "-", "SUB_F", PC_ADDSUB, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {6, "-", "SUB_V", PC_ADDSUB, ASSOC_LEFT, &type_vector, &type_vector, &type_vector, OPF_STD}, - {6, "==", "EQ_F", PC_EQUALITY, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {6, "==", "EQ_V", PC_EQUALITY, ASSOC_LEFT, &type_vector, &type_vector, &type_float}, - {6, "==", "EQ_S", PC_EQUALITY, ASSOC_LEFT, &type_string, &type_string, &type_float}, - {6, "==", "EQ_E", PC_EQUALITY, ASSOC_LEFT, &type_entity, &type_entity, &type_float}, - {6, "==", "EQ_FNC", PC_EQUALITY, ASSOC_LEFT, &type_function, &type_function, &type_float}, + {6, "==", "EQ_F", PC_EQUALITY, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {6, "==", "EQ_V", PC_EQUALITY, ASSOC_LEFT, &type_vector, &type_vector, &type_float, OPF_STD}, + {6, "==", "EQ_S", PC_EQUALITY, ASSOC_LEFT, &type_string, &type_string, &type_float, OPF_STD}, + {6, "==", "EQ_E", PC_EQUALITY, ASSOC_LEFT, &type_entity, &type_entity, &type_float, OPF_STD}, + {6, "==", "EQ_FNC", PC_EQUALITY, ASSOC_LEFT, &type_function, &type_function, &type_float,OPF_STD}, - {6, "!=", "NE_F", PC_EQUALITY, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {6, "!=", "NE_V", PC_EQUALITY, ASSOC_LEFT, &type_vector, &type_vector, &type_float}, - {6, "!=", "NE_S", PC_EQUALITY, ASSOC_LEFT, &type_string, &type_string, &type_float}, - {6, "!=", "NE_E", PC_EQUALITY, ASSOC_LEFT, &type_entity, &type_entity, &type_float}, - {6, "!=", "NE_FNC", PC_EQUALITY, ASSOC_LEFT, &type_function, &type_function, &type_float}, + {6, "!=", "NE_F", PC_EQUALITY, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {6, "!=", "NE_V", PC_EQUALITY, ASSOC_LEFT, &type_vector, &type_vector, &type_float, OPF_STD}, + {6, "!=", "NE_S", PC_EQUALITY, ASSOC_LEFT, &type_string, &type_string, &type_float, OPF_STD}, + {6, "!=", "NE_E", PC_EQUALITY, ASSOC_LEFT, &type_entity, &type_entity, &type_float, OPF_STD}, + {6, "!=", "NE_FNC", PC_EQUALITY, ASSOC_LEFT, &type_function, &type_function, &type_float,OPF_STD}, - {6, "<=", "LE_F", PC_RELATION, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {6, ">=", "GE_F", PC_RELATION, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {6, "<", "LT_F", PC_RELATION, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {6, ">", "GT_F", PC_RELATION, ASSOC_LEFT, &type_float, &type_float, &type_float}, + {6, "<=", "LE_F", PC_RELATION, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {6, ">=", "GE_F", PC_RELATION, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {6, "<", "LT_F", PC_RELATION, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {6, ">", "GT_F", PC_RELATION, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, - {6, ".", "LOADF_F", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_float}, - {6, ".", "LOADF_V", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_vector}, - {6, ".", "LOADF_S", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_string}, - {6, ".", "LOADF_E", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_entity}, - {6, ".", "LOADF_FI", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_field}, - {6, ".", "LOADF_FU", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_function}, + {6, ".", "LOADF_F", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_float}, + {6, ".", "LOADF_V", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_vector}, + {6, ".", "LOADF_S", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_string}, + {6, ".", "LOADF_E", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_entity}, + {6, ".", "LOADF_FI", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_field}, + {6, ".", "LOADF_FU", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_function}, - {6, ".", "FLDADDRESS", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_pointer}, + {6, ".", "FLDADDRESS", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_pointer}, - {6, "=", "STORE_F", PC_STORE, ASSOC_RIGHT, &type_float, &type_float, &type_float}, - {6, "=", "STORE_V", PC_STORE, ASSOC_RIGHT, &type_vector, &type_vector, &type_vector}, - {6, "=", "STORE_S", PC_STORE, ASSOC_RIGHT, &type_string, &type_string, &type_string}, - {6, "=", "STORE_ENT", PC_STORE, ASSOC_RIGHT, &type_entity, &type_entity, &type_entity}, - {6, "=", "STORE_FLD", PC_STORE, ASSOC_RIGHT, &type_field, &type_field, &type_field}, - {6, "=", "STORE_FNC", PC_STORE, ASSOC_RIGHT, &type_function, &type_function, &type_function}, + {6, "=", "STORE_F", PC_STORE, ASSOC_RIGHT, &type_float, &type_float, &type_float, OPF_STORE}, + {6, "=", "STORE_V", PC_STORE, ASSOC_RIGHT, &type_vector, &type_vector, &type_vector, OPF_STORE}, + {6, "=", "STORE_S", PC_STORE, ASSOC_RIGHT, &type_string, &type_string, &type_string, OPF_STORE}, + {6, "=", "STORE_ENT", PC_STORE, ASSOC_RIGHT, &type_entity, &type_entity, &type_entity, OPF_STORE}, + {6, "=", "STORE_FLD", PC_STORE, ASSOC_RIGHT, &type_field, &type_field, &type_field, OPF_STORE}, + {6, "=", "STORE_FNC", PC_STORE, ASSOC_RIGHT, &type_function, &type_function, &type_function, OPF_STORE}, - {6, "=", "STOREP_F", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_float, &type_float}, - {6, "=", "STOREP_V", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_vector, &type_vector}, - {6, "=", "STOREP_S", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_string, &type_string}, - {6, "=", "STOREP_ENT", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_entity, &type_entity}, - {6, "=", "STOREP_FLD", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_field, &type_field}, - {6, "=", "STOREP_FNC", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_function, &type_function}, + {6, "=", "STOREP_F", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_float, &type_float, OPF_STOREPTR}, + {6, "=", "STOREP_V", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_vector, &type_vector, OPF_STOREPTR}, + {6, "=", "STOREP_S", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_string, &type_string, OPF_STOREPTR}, + {6, "=", "STOREP_ENT", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_entity, &type_entity, OPF_STOREPTR}, + {6, "=", "STOREP_FLD", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_field, &type_field, OPF_STOREPTR}, + {6, "=", "STOREP_FNC", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_function, &type_function, OPF_STOREPTR}, {6, "", "RETURN", PC_NONE, ASSOC_LEFT, &type_vector, &type_void, &type_void}, - {6, "!", "NOT_F", PC_UNARY, ASSOC_LEFT, &type_float, &type_void, &type_float}, - {6, "!", "NOT_V", PC_UNARY, ASSOC_LEFT, &type_vector, &type_void, &type_float}, - {6, "!", "NOT_S", PC_UNARY, ASSOC_LEFT, &type_vector, &type_void, &type_float}, - {6, "!", "NOT_ENT", PC_UNARY, ASSOC_LEFT, &type_entity, &type_void, &type_float}, - {6, "!", "NOT_FNC", PC_UNARY, ASSOC_LEFT, &type_function, &type_void, &type_float}, + {6, "!", "NOT_F", PC_UNARY, ASSOC_LEFT, &type_float, &type_void, &type_float}, + {6, "!", "NOT_V", PC_UNARY, ASSOC_LEFT, &type_vector, &type_void, &type_float}, + {6, "!", "NOT_S", PC_UNARY, ASSOC_LEFT, &type_vector, &type_void, &type_float}, + {6, "!", "NOT_ENT", PC_UNARY, ASSOC_LEFT, &type_entity, &type_void, &type_float}, + {6, "!", "NOT_FNC", PC_UNARY, ASSOC_LEFT, &type_function, &type_void, &type_float}, - {6, "", "IF", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void}, - {6, "", "IFNOT", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void}, + {6, "", "IF", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void}, + {6, "", "IFNOT", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void}, // calls returns REG_RETURN - {6, "", "CALL0", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, - {6, "", "CALL1", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, - {6, "", "CALL2", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, - {6, "", "CALL3", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, - {6, "", "CALL4", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, - {6, "", "CALL5", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, - {6, "", "CALL6", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, - {6, "", "CALL7", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, - {6, "", "CALL8", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, + {6, "", "CALL0", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, + {6, "", "CALL1", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, + {6, "", "CALL2", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, + {6, "", "CALL3", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, + {6, "", "CALL4", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, + {6, "", "CALL5", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, + {6, "", "CALL6", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, + {6, "", "CALL7", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, + {6, "", "CALL8", PC_NONE, ASSOC_LEFT, &type_function, &type_void, &type_void}, - {6, "", "STATE", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_void}, + {6, "", "STATE", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_void}, - {6, "", "GOTO", PC_NONE, ASSOC_RIGHT, NULL, &type_void, &type_void}, + {6, "", "GOTO", PC_NONE, ASSOC_RIGHT, NULL, &type_void, &type_void}, - {6, "&&", "AND_F", PC_LOGICAND, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {6, "||", "OR_F", PC_LOGICOR, ASSOC_LEFT, &type_float, &type_float, &type_float}, + {6, "&&", "AND_F", PC_LOGICAND, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {6, "||", "OR_F", PC_LOGICOR, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, - {6, "&", "BITAND", PC_BITAND, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {6, "|", "BITOR", PC_BITOR, ASSOC_LEFT, &type_float, &type_float, &type_float}, + {6, "&", "BITAND", PC_BITAND, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {6, "|", "BITOR", PC_BITOR, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, //version 6 are in normal progs. //these are hexen2 - {7, "*=", "MULSTORE_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float}, - {7, "*=", "MULSTORE_VF", PC_STORE, ASSOC_RIGHT_RESULT, &type_vector, &type_float, &type_vector}, - {7, "*=", "MULSTOREP_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float}, - {7, "*=", "MULSTOREP_VF", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_vector}, + {7, "*=", "MULSTORE_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float, OPF_STORE}, + {7, "*=", "MULSTORE_VF", PC_STORE, ASSOC_RIGHT_RESULT, &type_vector, &type_float, &type_vector, OPF_STORE}, + {7, "*=", "MULSTOREP_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float, OPF_STOREPTR}, + {7, "*=", "MULSTOREP_VF", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_vector, OPF_STOREPTR}, - {7, "/=", "DIVSTORE_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float}, - {7, "/=", "DIVSTOREP_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float}, + {7, "/=", "DIVSTORE_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float, OPF_STORE}, + {7, "/=", "DIVSTOREP_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float, OPF_STOREPTR}, - {7, "+=", "ADDSTORE_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float}, - {7, "+=", "ADDSTORE_V", PC_STORE, ASSOC_RIGHT_RESULT, &type_vector, &type_vector, &type_vector}, - {7, "+=", "ADDSTOREP_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float}, - {7, "+=", "ADDSTOREP_V", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_vector, &type_vector}, + {7, "+=", "ADDSTORE_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float, OPF_STORE}, + {7, "+=", "ADDSTORE_V", PC_STORE, ASSOC_RIGHT_RESULT, &type_vector, &type_vector, &type_vector, OPF_STORE}, + {7, "+=", "ADDSTOREP_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float, OPF_STOREPTR}, + {7, "+=", "ADDSTOREP_V", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_vector, &type_vector, OPF_STOREPTR}, - {7, "-=", "SUBSTORE_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float}, - {7, "-=", "SUBSTORE_V", PC_STORE, ASSOC_RIGHT_RESULT, &type_vector, &type_vector, &type_vector}, - {7, "-=", "SUBSTOREP_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float}, - {7, "-=", "SUBSTOREP_V", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_vector, &type_vector}, + {7, "-=", "SUBSTORE_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float, OPF_STORE}, + {7, "-=", "SUBSTORE_V", PC_STORE, ASSOC_RIGHT_RESULT, &type_vector, &type_vector, &type_vector, OPF_STORE}, + {7, "-=", "SUBSTOREP_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_float, OPF_STOREPTR}, + {7, "-=", "SUBSTOREP_V", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_vector, &type_vector, OPF_STOREPTR}, {7, "", "FETCH_GBL_F", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, {7, "", "FETCH_GBL_V", PC_NONE, ASSOC_LEFT, &type_vector, &type_float, &type_vector}, @@ -456,10 +456,10 @@ QCC_opcode_t pr_opcodes[] = {7, "", "THINKTIME", PC_NONE, ASSOC_LEFT, &type_entity, &type_float, &type_void}, - {7, "|=", "BITSETSTORE_F", PC_STORE, ASSOC_RIGHT, &type_float, &type_float, &type_float}, - {7, "|=", "BITSETSTOREP_F", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_float, &type_float}, - {7, "&~=", "BITCLRSTORE_F", PC_STORE, ASSOC_RIGHT, &type_float, &type_float, &type_float}, - {7, "&~=", "BITCLRSTOREP_F", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_float, &type_float}, + {7, "|=", "BITSETSTORE_F", PC_STORE, ASSOC_RIGHT, &type_float, &type_float, &type_float, OPF_STORE}, + {7, "|=", "BITSETSTOREP_F", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_float, &type_float,OPF_STOREPTR}, + {7, "&~=", "BITCLRSTORE_F", PC_STORE, ASSOC_RIGHT, &type_float, &type_float, &type_float, OPF_STORE}, + {7, "&~=", "BITCLRSTOREP_F", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_float, &type_float,OPF_STOREPTR}, {7, "", "RAND0", PC_NONE, ASSOC_LEFT, &type_void, &type_void, &type_float}, {7, "", "RAND1", PC_NONE, ASSOC_LEFT, &type_float, &type_void, &type_float}, @@ -480,268 +480,271 @@ QCC_opcode_t pr_opcodes[] = //Later are additions by DMW. - {7, "", "CALL1H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_void}, - {7, "", "CALL2H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, - {7, "", "CALL3H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, - {7, "", "CALL4H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, - {7, "", "CALL5H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, - {7, "", "CALL6H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, - {7, "", "CALL7H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, - {7, "", "CALL8H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, + {7, "", "CALL1H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_void}, + {7, "", "CALL2H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, + {7, "", "CALL3H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, + {7, "", "CALL4H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, + {7, "", "CALL5H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, + {7, "", "CALL6H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, + {7, "", "CALL7H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, + {7, "", "CALL8H", PC_NONE, ASSOC_RIGHT, &type_function, &type_variant, &type_variant}, - {7, "=", "STORE_I", PC_STORE, ASSOC_RIGHT, &type_integer, &type_integer, &type_integer}, - {7, "=", "STORE_IF", PC_STORE, ASSOC_RIGHT, &type_float, &type_integer, &type_integer}, - {7, "=", "STORE_FI", PC_STORE, ASSOC_RIGHT, &type_integer, &type_float, &type_float}, + {7, "=", "STORE_I", PC_STORE, ASSOC_RIGHT, &type_integer, &type_integer, &type_integer, OPF_STORE}, + {7, "=", "STORE_IF", PC_STORE, ASSOC_RIGHT, &type_float, &type_integer, &type_integer, OPF_STORE}, + {7, "=", "STORE_FI", PC_STORE, ASSOC_RIGHT, &type_integer, &type_float, &type_float, OPF_STORE}, - {7, "+", "ADD_I", PC_ADDSUB, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, "+", "ADD_FI", PC_ADDSUB, ASSOC_LEFT, &type_float, &type_integer, &type_float}, - {7, "+", "ADD_IF", PC_ADDSUB, ASSOC_LEFT, &type_integer, &type_float, &type_float}, + {7, "+", "ADD_I", PC_ADDSUB, ASSOC_LEFT, &type_integer, &type_integer, &type_integer,OPF_STD}, + {7, "+", "ADD_FI", PC_ADDSUB, ASSOC_LEFT, &type_float, &type_integer, &type_float, OPF_STD}, + {7, "+", "ADD_IF", PC_ADDSUB, ASSOC_LEFT, &type_integer, &type_float, &type_float, OPF_STD}, - {7, "-", "SUB_I", PC_ADDSUB, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, "-", "SUB_FI", PC_ADDSUB, ASSOC_LEFT, &type_float, &type_integer, &type_float}, - {7, "-", "SUB_IF", PC_ADDSUB, ASSOC_LEFT, &type_integer, &type_float, &type_float}, + {7, "-", "SUB_I", PC_ADDSUB, ASSOC_LEFT, &type_integer, &type_integer, &type_integer,OPF_STD}, + {7, "-", "SUB_FI", PC_ADDSUB, ASSOC_LEFT, &type_float, &type_integer, &type_float, OPF_STD}, + {7, "-", "SUB_IF", PC_ADDSUB, ASSOC_LEFT, &type_integer, &type_float, &type_float, OPF_STD}, - {7, "", "C_ITOF", PC_STORE, ASSOC_LEFT, &type_integer, &type_void, &type_float}, - {7, "", "C_FTOI", PC_STORE, ASSOC_LEFT, &type_float, &type_void, &type_integer}, - {7, "", "CP_ITOF", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_float}, - {7, "", "CP_FTOI", PC_STORE, ASSOC_LEFT, &type_pointer, &type_float, &type_integer}, + {7, "", "C_ITOF", PC_STORE, ASSOC_LEFT, &type_integer, &type_void, &type_float}, + {7, "", "C_FTOI", PC_STORE, ASSOC_LEFT, &type_float, &type_void, &type_integer}, + {7, "", "CP_ITOF", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_float}, + {7, "", "CP_FTOI", PC_STORE, ASSOC_LEFT, &type_pointer, &type_float, &type_integer}, - {7, ".", "LOADF_I", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_integer}, - {7, "=", "STOREP_I", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_integer, &type_integer}, - {7, "=", "STOREP_IF", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_float, &type_integer}, - {7, "=", "STOREP_FI", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_integer, &type_float}, + {7, ".", "LOADF_I", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_integer}, + {7, "=", "STOREP_I", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_integer, &type_integer, OPF_STOREPTR}, + {7, "=", "STOREP_IF", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_float, &type_integer, OPF_STOREPTR}, + {7, "=", "STOREP_FI", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_integer, &type_float, OPF_STOREPTR}, - {7, "&", "BITAND_I", PC_BITAND, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, "|", "BITOR_I", PC_BITOR, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, + {7, "&", "BITAND_I", PC_BITAND, ASSOC_LEFT, &type_integer, &type_integer, &type_integer,OPF_STD}, + {7, "|", "BITOR_I", PC_BITOR, ASSOC_LEFT, &type_integer, &type_integer, &type_integer,OPF_STD}, - {7, "*", "MUL_I", PC_MULDIV, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, "/", "DIV_I", PC_MULDIV, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, "==", "EQ_I", PC_EQUALITY, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, "!=", "NE_I", PC_EQUALITY, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, + {7, "*", "MUL_I", PC_MULDIV, ASSOC_LEFT, &type_integer, &type_integer, &type_integer,OPF_STD}, + {7, "/", "DIV_I", PC_MULDIV, ASSOC_LEFT, &type_integer, &type_integer, &type_integer,OPF_STD}, + {7, "==", "EQ_I", PC_EQUALITY, ASSOC_LEFT, &type_integer, &type_integer, &type_integer,OPF_STD}, + {7, "!=", "NE_I", PC_EQUALITY, ASSOC_LEFT, &type_integer, &type_integer, &type_integer,OPF_STD}, {7, "", "IFNOTS", PC_NONE, ASSOC_RIGHT, &type_string, NULL, &type_void}, - {7, "", "IFS", PC_NONE, ASSOC_RIGHT, &type_string, NULL, &type_void}, + {7, "", "IFS", PC_NONE, ASSOC_RIGHT, &type_string, NULL, &type_void}, - {7, "!", "NOT_I", PC_UNARY, ASSOC_LEFT, &type_integer, &type_void, &type_integer}, + {7, "!", "NOT_I", PC_UNARY, ASSOC_LEFT, &type_integer, &type_void, &type_integer}, - {7, "/", "DIV_VF", PC_MULDIV, ASSOC_LEFT, &type_vector, &type_float, &type_vector}, + {7, "/", "DIV_VF", PC_MULDIV, ASSOC_LEFT, &type_vector, &type_float, &type_vector, OPF_STD}, - {7, "^", "BITXOR_I", PC_BITXOR, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, ">>", "RSHIFT_I", PC_SHIFT, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, "<<", "LSHIFT_I", PC_SHIFT, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, + {7, "^", "BITXOR_I", PC_BITXOR, ASSOC_LEFT, &type_integer, &type_integer, &type_integer,OPF_STD}, + {7, ">>", "RSHIFT_I", PC_SHIFT, ASSOC_LEFT, &type_integer, &type_integer, &type_integer,OPF_STD}, + {7, "<<", "LSHIFT_I", PC_SHIFT, ASSOC_LEFT, &type_integer, &type_integer, &type_integer,OPF_STD}, //var, offset return {7, "", "GLOBALADDRESS", PC_NONE, ASSOC_LEFT, &type_float, &type_integer, &type_pointer}, - {7, "", "ADD_PIW", PC_NONE, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer}, + {7, "", "ADD_PIW", PC_NONE, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer}, - {7, "=", "LOADA_F", PC_STORE, ASSOC_LEFT, &type_float, &type_integer, &type_float}, - {7, "=", "LOADA_V", PC_STORE, ASSOC_LEFT, &type_vector, &type_integer, &type_vector}, - {7, "=", "LOADA_S", PC_STORE, ASSOC_LEFT, &type_string, &type_integer, &type_string}, + {7, "=", "LOADA_F", PC_STORE, ASSOC_LEFT, &type_float, &type_integer, &type_float}, + {7, "=", "LOADA_V", PC_STORE, ASSOC_LEFT, &type_vector, &type_integer, &type_vector}, + {7, "=", "LOADA_S", PC_STORE, ASSOC_LEFT, &type_string, &type_integer, &type_string}, {7, "=", "LOADA_ENT", PC_STORE, ASSOC_LEFT, &type_entity, &type_integer, &type_entity}, {7, "=", "LOADA_FLD", PC_STORE, ASSOC_LEFT, &type_field, &type_integer, &type_field}, {7, "=", "LOADA_FNC", PC_STORE, ASSOC_LEFT, &type_function, &type_integer, &type_function}, - {7, "=", "LOADA_I", PC_STORE, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, + {7, "=", "LOADA_I", PC_STORE, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, "=", "STORE_P", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_void}, - {7, ".", "LOADF_P", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_pointer}, + {7, "=", "STORE_P", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_void, OPF_STORE}, + {7, ".", "LOADF_P", PC_MEMBER, ASSOC_LEFT, &type_entity, &type_field, &type_pointer}, - {7, "=", "LOADP_F", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_float}, - {7, "=", "LOADP_V", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_vector}, - {7, "=", "LOADP_S", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_string}, - {7, "=", "LOADP_ENT", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_entity}, - {7, "=", "LOADP_FLD", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_field}, - {7, "=", "LOADP_FNC", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_function}, - {7, "=", "LOADP_I", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_integer}, + {7, "=", "LOADP_F", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_float, OPF_LOADPTR}, + {7, "=", "LOADP_V", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_vector, OPF_LOADPTR}, + {7, "=", "LOADP_S", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_string, OPF_LOADPTR}, + {7, "=", "LOADP_ENT", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_entity, OPF_LOADPTR}, + {7, "=", "LOADP_FLD", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_field, OPF_LOADPTR}, + {7, "=", "LOADP_FNC", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_function, OPF_LOADPTR}, + {7, "=", "LOADP_I", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_integer, OPF_LOADPTR}, - {7, "<=", "LE_I", PC_RELATION, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, ">=", "GE_I", PC_RELATION, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, "<", "LT_I", PC_RELATION, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, ">", "GT_I", PC_RELATION, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, + {7, "<=", "LE_I", PC_RELATION, ASSOC_LEFT, &type_integer, &type_integer, &type_integer, OPF_STD}, + {7, ">=", "GE_I", PC_RELATION, ASSOC_LEFT, &type_integer, &type_integer, &type_integer, OPF_STD}, + {7, "<", "LT_I", PC_RELATION, ASSOC_LEFT, &type_integer, &type_integer, &type_integer, OPF_STD}, + {7, ">", "GT_I", PC_RELATION, ASSOC_LEFT, &type_integer, &type_integer, &type_integer, OPF_STD}, - {7, "<=", "LE_IF", PC_RELATION, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, - {7, ">=", "GE_IF", PC_RELATION, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, - {7, "<", "LT_IF", PC_RELATION, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, - {7, ">", "GT_IF", PC_RELATION, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, + {7, "<=", "LE_IF", PC_RELATION, ASSOC_LEFT, &type_integer, &type_float, &type_integer, OPF_STD}, + {7, ">=", "GE_IF", PC_RELATION, ASSOC_LEFT, &type_integer, &type_float, &type_integer, OPF_STD}, + {7, "<", "LT_IF", PC_RELATION, ASSOC_LEFT, &type_integer, &type_float, &type_integer, OPF_STD}, + {7, ">", "GT_IF", PC_RELATION, ASSOC_LEFT, &type_integer, &type_float, &type_integer, OPF_STD}, - {7, "<=", "LE_FI", PC_RELATION, ASSOC_LEFT, &type_float, &type_integer, &type_integer}, - {7, ">=", "GE_FI", PC_RELATION, ASSOC_LEFT, &type_float, &type_integer, &type_integer}, - {7, "<", "LT_FI", PC_RELATION, ASSOC_LEFT, &type_float, &type_integer, &type_integer}, - {7, ">", "GT_FI", PC_RELATION, ASSOC_LEFT, &type_float, &type_integer, &type_integer}, + {7, "<=", "LE_FI", PC_RELATION, ASSOC_LEFT, &type_float, &type_integer, &type_integer, OPF_STD}, + {7, ">=", "GE_FI", PC_RELATION, ASSOC_LEFT, &type_float, &type_integer, &type_integer, OPF_STD}, + {7, "<", "LT_FI", PC_RELATION, ASSOC_LEFT, &type_float, &type_integer, &type_integer, OPF_STD}, + {7, ">", "GT_FI", PC_RELATION, ASSOC_LEFT, &type_float, &type_integer, &type_integer, OPF_STD}, - {7, "==", "EQ_IF", PC_EQUALITY, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, - {7, "==", "EQ_FI", PC_EQUALITY, ASSOC_LEFT, &type_float, &type_integer, &type_float}, + {7, "==", "EQ_IF", PC_EQUALITY, ASSOC_LEFT, &type_integer, &type_float, &type_integer, OPF_STD}, + {7, "==", "EQ_FI", PC_EQUALITY, ASSOC_LEFT, &type_float, &type_integer, &type_float, OPF_STD}, //------------------------------------- //string manipulation. - {7, "+", "ADD_SF", PC_ADDSUB, ASSOC_LEFT, &type_string, &type_float, &type_string}, - {7, "-", "SUB_S", PC_ADDSUB, ASSOC_LEFT, &type_string, &type_string, &type_float}, + {7, "+", "ADD_SF", PC_ADDSUB, ASSOC_LEFT, &type_string, &type_float, &type_string, OPF_STD}, + {7, "-", "SUB_S", PC_ADDSUB, ASSOC_LEFT, &type_string, &type_string, &type_float, OPF_STD}, {7, "", "STOREP_C", PC_STORE, ASSOC_RIGHT, &type_string, &type_float, &type_float}, - {7, "", "LOADP_C", PC_STORE, ASSOC_LEFT, &type_string, &type_float, &type_float}, + {7, "", "LOADP_C", PC_STORE, ASSOC_LEFT, &type_string, &type_float, &type_float, OPF_LOADPTR}, //------------------------------------- -{7, "*", "MUL_IF", PC_MULDIV, ASSOC_LEFT, &type_integer, &type_float, &type_float}, -{7, "*", "MUL_FI", PC_MULDIV, ASSOC_LEFT, &type_float, &type_integer, &type_float}, -{7, "*", "MUL_VI", PC_MULDIV, ASSOC_LEFT, &type_vector, &type_integer, &type_vector}, -{7, "*", "MUL_IV", PC_MULDIV, ASSOC_LEFT, &type_integer, &type_vector, &type_vector}, +{7, "*", "MUL_IF", PC_MULDIV, ASSOC_LEFT, &type_integer, &type_float, &type_float, OPF_STD}, +{7, "*", "MUL_FI", PC_MULDIV, ASSOC_LEFT, &type_float, &type_integer, &type_float, OPF_STD}, +{7, "*", "MUL_VI", PC_MULDIV, ASSOC_LEFT, &type_vector, &type_integer, &type_vector, OPF_STD}, +{7, "*", "MUL_IV", PC_MULDIV, ASSOC_LEFT, &type_integer, &type_vector, &type_vector, OPF_STD}, -{7, "/", "DIV_IF", PC_MULDIV, ASSOC_LEFT, &type_integer, &type_float, &type_float}, -{7, "/", "DIV_FI", PC_MULDIV, ASSOC_LEFT, &type_float, &type_integer, &type_float}, +{7, "/", "DIV_IF", PC_MULDIV, ASSOC_LEFT, &type_integer, &type_float, &type_float, OPF_STD}, +{7, "/", "DIV_FI", PC_MULDIV, ASSOC_LEFT, &type_float, &type_integer, &type_float, OPF_STD}, -{7, "&", "BITAND_IF", PC_BITAND, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, -{7, "|", "BITOR_IF", PC_BITOR, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, -{7, "&", "BITAND_FI", PC_BITAND, ASSOC_LEFT, &type_float, &type_integer, &type_integer}, -{7, "|", "BITOR_FI", PC_BITOR, ASSOC_LEFT, &type_float, &type_integer, &type_integer}, +{7, "&", "BITAND_IF", PC_BITAND, ASSOC_LEFT, &type_integer, &type_float, &type_integer, OPF_STD}, +{7, "|", "BITOR_IF", PC_BITOR, ASSOC_LEFT, &type_integer, &type_float, &type_integer, OPF_STD}, +{7, "&", "BITAND_FI", PC_BITAND, ASSOC_LEFT, &type_float, &type_integer, &type_integer, OPF_STD}, +{7, "|", "BITOR_FI", PC_BITOR, ASSOC_LEFT, &type_float, &type_integer, &type_integer, OPF_STD}, -{7, "&&", "AND_I", PC_LOGICAND, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, -{7, "||", "OR_I", PC_LOGICOR, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, -{7, "&&", "AND_IF", PC_LOGICAND, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, -{7, "||", "OR_IF", PC_LOGICOR, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, -{7, "&&", "AND_FI", PC_LOGICAND, ASSOC_LEFT, &type_float, &type_integer, &type_integer}, -{7, "||", "OR_FI", PC_LOGICOR, ASSOC_LEFT, &type_float, &type_integer, &type_integer}, -{7, "!=", "NE_IF", PC_EQUALITY, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, -{7, "!=", "NE_FI", PC_EQUALITY, ASSOC_LEFT, &type_float, &type_integer, &type_integer}, +{7, "&&", "AND_I", PC_LOGICAND, ASSOC_LEFT, &type_integer, &type_integer, &type_integer, OPF_STD}, +{7, "||", "OR_I", PC_LOGICOR, ASSOC_LEFT, &type_integer, &type_integer, &type_integer, OPF_STD}, +{7, "&&", "AND_IF", PC_LOGICAND, ASSOC_LEFT, &type_integer, &type_float, &type_integer, OPF_STD}, +{7, "||", "OR_IF", PC_LOGICOR, ASSOC_LEFT, &type_integer, &type_float, &type_integer, OPF_STD}, +{7, "&&", "AND_FI", PC_LOGICAND, ASSOC_LEFT, &type_float, &type_integer, &type_integer, OPF_STD}, +{7, "||", "OR_FI", PC_LOGICOR, ASSOC_LEFT, &type_float, &type_integer, &type_integer, OPF_STD}, +{7, "!=", "NE_IF", PC_EQUALITY, ASSOC_LEFT, &type_integer, &type_float, &type_integer, OPF_STD}, +{7, "!=", "NE_FI", PC_EQUALITY, ASSOC_LEFT, &type_float, &type_integer, &type_integer, OPF_STD}, -{7, "<>", "GSTOREP_I", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GSTOREP_F", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GSTOREP_ENT", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GSTOREP_FLD", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GSTOREP_S", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GSTOREP_FNC", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GSTOREP_V", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTOREP_I", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTOREP_F", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTOREP_ENT", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTOREP_FLD", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTOREP_S", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTOREP_FNC", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTOREP_V", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GADDRESS", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GADDRESS", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GLOAD_I", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GLOAD_F", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GLOAD_FLD", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GLOAD_ENT", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GLOAD_S", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GLOAD_FNC", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_I", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_F", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_FLD", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_ENT", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_S", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GLOAD_FNC", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "BOUNDCHECK", PC_NONE, ASSOC_LEFT, &type_integer, NULL, NULL}, +{7, "<>", "BOUNDCHECK", PC_NONE, ASSOC_LEFT, &type_integer, NULL, NULL}, -{7, "", "UNUSED", PC_NONE, ASSOC_RIGHT, &type_void, &type_void, &type_void}, -{7, "", "PUSH", PC_NONE, ASSOC_RIGHT, &type_float, &type_void, &type_pointer}, -{7, "", "POP", PC_NONE, ASSOC_RIGHT, &type_float, &type_void, &type_void}, +{7, "", "UNUSED", PC_NONE, ASSOC_RIGHT, &type_void, &type_void, &type_void}, +{7, "", "PUSH", PC_NONE, ASSOC_RIGHT, &type_float, &type_void, &type_pointer}, +{7, "", "POP", PC_NONE, ASSOC_RIGHT, &type_float, &type_void, &type_void}, -{7, "", "SWITCH_I",PC_NONE, ASSOC_LEFT, &type_void, NULL, &type_void}, -{7, "<>", "GLOAD_S", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "", "SWITCH_I",PC_NONE, ASSOC_LEFT, &type_void, NULL, &type_void}, +{7, "<>", "GLOAD_S", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "", "IF_F", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void}, -{7, "","IFNOT_F", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void}, +{7, "", "IF_F", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void}, +{7, "","IFNOT_F", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void}, /* -{7, "<=>", "STOREF_F", PC_STORE, ASSOC_RIGHT, &type_entity, &type_field, &type_float}, -{7, "<=>", "STOREF_V", PC_STORE, ASSOC_RIGHT, &type_entity, &type_field, &type_vector}, -{7, "<=>", "STOREF_IF", PC_STORE, ASSOC_RIGHT, &type_entity, &type_field, &type_float}, -{7, "<=>", "STOREF_FI", PC_STORE, ASSOC_RIGHT, &type_entity, &type_field, &type_float}, +{7, "<=>", "STOREF_F", PC_STORE, ASSOC_RIGHT, &type_entity, &type_field, &type_float}, +{7, "<=>", "STOREF_V", PC_STORE, ASSOC_RIGHT, &type_entity, &type_field, &type_vector}, +{7, "<=>", "STOREF_IF", PC_STORE, ASSOC_RIGHT, &type_entity, &type_field, &type_float}, +{7, "<=>", "STOREF_FI", PC_STORE, ASSOC_RIGHT, &type_entity, &type_field, &type_float}, */ /* emulated ops begin here */ {7, "<>", "OP_EMULATED", PC_NONE, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {7, "|=", "BITSET_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, - {7, "|=", "BITSETP_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer}, - {7, "&~=", "BITCLR_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, + {7, "|=", "BITSET_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer, OPF_STORE}, + {7, "|=", "BITSETP_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer, OPF_STOREPTR}, + {7, "&~=", "BITCLR_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer, OPF_STORE}, - {7, "*=", "MULSTORE_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, - {7, "/=", "DIVSTORE_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, - {7, "+=", "ADDSTORE_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, - {7, "-=", "SUBSTORE_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, + {7, "*=", "MULSTORE_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer, OPF_STORE}, + {7, "/=", "DIVSTORE_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer, OPF_STORE}, + {7, "+=", "ADDSTORE_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer, OPF_STORE}, + {7, "-=", "SUBSTORE_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer, OPF_STORE}, - {7, "*=", "MULSTOREP_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer}, - {7, "/=", "DIVSTOREP_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer}, - {7, "+=", "ADDSTOREP_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer}, - {7, "-=", "SUBSTOREP_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer}, + {7, "*=", "MULSTOREP_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer, OPF_STOREPTR}, + {7, "/=", "DIVSTOREP_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer, OPF_STOREPTR}, + {7, "+=", "ADDSTOREP_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer, OPF_STOREPTR}, + {7, "-=", "SUBSTOREP_I", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer, OPF_STOREPTR}, - {7, "*=", "MULSTORE_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float}, - {7, "*=", "MULSTOREP_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float}, - {7, "/=", "DIVSTORE_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float}, - {7, "/=", "DIVSTOREP_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float}, - {7, "+=", "ADDSTORE_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float}, - {7, "+=", "ADDSTOREP_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float}, - {7, "-=", "SUBSTORE_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float}, - {7, "-=", "SUBSTOREP_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float}, + {7, "*=", "MULSTORE_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float, OPF_STORE}, + {7, "*=", "MULSTOREP_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float, OPF_STOREPTR}, + {7, "/=", "DIVSTORE_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float, OPF_STORE}, + {7, "/=", "DIVSTOREP_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float, OPF_STOREPTR}, + {7, "+=", "ADDSTORE_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float, OPF_STORE}, + {7, "+=", "ADDSTOREP_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float, OPF_STOREPTR}, + {7, "-=", "SUBSTORE_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_integer, &type_float, &type_float, OPF_STORE}, + {7, "-=", "SUBSTOREP_IF", PC_STORE, ASSOC_RIGHT_RESULT, &type_intpointer, &type_float, &type_float, OPF_STOREPTR}, - {7, "*=", "MULSTORE_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float}, - {7, "*=", "MULSTOREP_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float}, - {7, "/=", "DIVSTORE_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float}, - {7, "/=", "DIVSTOREP_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float}, - {7, "+=", "ADDSTORE_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float}, - {7, "+=", "ADDSTOREP_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float}, - {7, "-=", "SUBSTORE_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float}, - {7, "-=", "SUBSTOREP_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float}, + {7, "*=", "MULSTORE_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float, OPF_STORE}, + {7, "*=", "MULSTOREP_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float, OPF_STOREPTR}, + {7, "/=", "DIVSTORE_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float, OPF_STORE}, + {7, "/=", "DIVSTOREP_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float, OPF_STOREPTR}, + {7, "+=", "ADDSTORE_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float, OPF_STORE}, + {7, "+=", "ADDSTOREP_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float, OPF_STOREPTR}, + {7, "-=", "SUBSTORE_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_integer, &type_float, OPF_STORE}, + {7, "-=", "SUBSTOREP_FI", PC_STORE, ASSOC_RIGHT_RESULT, &type_floatpointer, &type_integer, &type_float, OPF_STOREPTR}, - {7, "*=", "MULSTORE_VI", PC_STORE, ASSOC_RIGHT_RESULT, &type_vector, &type_integer, &type_vector}, - {7, "*=", "MULSTOREP_VI", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_vector}, + {7, "*=", "MULSTORE_VI", PC_STORE, ASSOC_RIGHT_RESULT, &type_vector, &type_integer, &type_vector, OPF_STORE}, + {7, "*=", "MULSTOREP_VI", PC_STORE, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_vector, OPF_STOREPTR}, {7, "=", "LOADA_STRUCT", PC_STORE, ASSOC_LEFT, &type_float, &type_integer, &type_float}, - {7, "=", "LOADP_P", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer}, - {7, "=", "STOREP_P", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_pointer}, + {7, "=", "LOADP_P", PC_STORE, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer, OPF_LOADPTR}, + {7, "=", "STOREP_P", PC_STORE, ASSOC_RIGHT, &type_pointer, &type_pointer, &type_pointer, OPF_STOREPTR}, {7, "~", "BITNOT_F", PC_UNARY, ASSOC_LEFT, &type_float, &type_void, &type_float}, {7, "~", "BITNOT_I", PC_UNARY, ASSOC_LEFT, &type_integer, &type_void, &type_integer}, - {7, "==", "EQ_P", PC_EQUALITY, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float}, - {7, "!=", "NE_P", PC_EQUALITY, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float}, - {7, "<=", "LE_P", PC_RELATION, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float}, - {7, ">=", "GE_P", PC_RELATION, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float}, - {7, "<", "LT_P", PC_RELATION, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float}, - {7, ">", "GT_P", PC_RELATION, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float}, + {7, "==", "EQ_P", PC_EQUALITY, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float, OPF_STD}, + {7, "!=", "NE_P", PC_EQUALITY, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float, OPF_STD}, + {7, "<=", "LE_P", PC_RELATION, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float, OPF_STD}, + {7, ">=", "GE_P", PC_RELATION, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float, OPF_STD}, + {7, "<", "LT_P", PC_RELATION, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float, OPF_STD}, + {7, ">", "GT_P", PC_RELATION, ASSOC_LEFT, &type_pointer, &type_pointer, &type_float, OPF_STD}, - {7, "&=", "ANDSTORE_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float}, - {7, "&~=", "BITCLR_F", PC_STORE, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {7, "&~=", "BITCLR_I", PC_STORE, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, + {7, "&=", "ANDSTORE_F", PC_STORE, ASSOC_RIGHT_RESULT, &type_float, &type_float, &type_float, OPF_STORE}, + {7, "&~=", "BITCLR_F", PC_STORE, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STORE}, + {7, "&~=", "BITCLR_I", PC_STORE, ASSOC_LEFT, &type_integer, &type_integer, &type_integer, OPF_STORE}, - {7, "+", "ADD_SI", PC_ADDSUB, ASSOC_LEFT, &type_string, &type_integer, &type_string}, - {7, "+", "ADD_IS", PC_ADDSUB, ASSOC_LEFT, &type_integer, &type_string, &type_string}, - {7, "+", "ADD_PF", PC_ADDSUB, ASSOC_LEFT, &type_pointer, &type_float, &type_pointer}, - {7, "+", "ADD_FP", PC_ADDSUB, ASSOC_LEFT, &type_float, &type_pointer, &type_pointer}, - {7, "+", "ADD_PI", PC_ADDSUB, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer}, - {7, "+", "ADD_IP", PC_ADDSUB, ASSOC_LEFT, &type_integer, &type_pointer, &type_pointer}, - {7, "-", "SUB_SI", PC_ADDSUB, ASSOC_LEFT, &type_string, &type_integer, &type_string}, - {7, "-", "SUB_PF", PC_ADDSUB, ASSOC_LEFT, &type_pointer, &type_float, &type_pointer}, - {7, "-", "SUB_PI", PC_ADDSUB, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer}, - {7, "-", "SUB_PP", PC_ADDSUB, ASSOC_LEFT, &type_pointer, &type_pointer, &type_integer}, + {7, "+", "ADD_SI", PC_ADDSUB, ASSOC_LEFT, &type_string, &type_integer, &type_string, OPF_STD}, + {7, "+", "ADD_IS", PC_ADDSUB, ASSOC_LEFT, &type_integer, &type_string, &type_string, OPF_STD}, + {7, "+", "ADD_PF", PC_ADDSUB, ASSOC_LEFT, &type_pointer, &type_float, &type_pointer, OPF_STD}, + {7, "+", "ADD_FP", PC_ADDSUB, ASSOC_LEFT, &type_float, &type_pointer, &type_pointer, OPF_STD}, + {7, "+", "ADD_PI", PC_ADDSUB, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer, OPF_STD}, + {7, "+", "ADD_IP", PC_ADDSUB, ASSOC_LEFT, &type_integer, &type_pointer, &type_pointer, OPF_STD}, + {7, "-", "SUB_SI", PC_ADDSUB, ASSOC_LEFT, &type_string, &type_integer, &type_string, OPF_STD}, + {7, "-", "SUB_PF", PC_ADDSUB, ASSOC_LEFT, &type_pointer, &type_float, &type_pointer, OPF_STD}, + {7, "-", "SUB_PI", PC_ADDSUB, ASSOC_LEFT, &type_pointer, &type_integer, &type_pointer, OPF_STD}, + {7, "-", "SUB_PP", PC_ADDSUB, ASSOC_LEFT, &type_pointer, &type_pointer, &type_integer, OPF_STD}, - {7, "%", "MOD_F", PC_MULDIV, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {7, "%", "MOD_I", PC_MULDIV, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, - {7, "%", "MOD_V", PC_MULDIV, ASSOC_LEFT, &type_vector, &type_vector, &type_vector}, + {7, "%", "MOD_F", PC_MULDIV, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {7, "%", "MOD_I", PC_MULDIV, ASSOC_LEFT, &type_integer, &type_integer, &type_integer, OPF_STD}, + {7, "%", "MOD_V", PC_MULDIV, ASSOC_LEFT, &type_vector, &type_vector, &type_vector, OPF_STD}, - {7, "^", "BITXOR_F", PC_BITXOR, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {7, ">>", "RSHIFT_F", PC_SHIFT, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {7, "<<", "LSHIFT_F", PC_SHIFT, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {7, ">>", "RSHIFT_IF", PC_SHIFT, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, - {7, "<<", "LSHIFT_IF", PC_SHIFT, ASSOC_LEFT, &type_integer, &type_float, &type_integer}, - {7, ">>", "RSHIFT_FI", PC_SHIFT, ASSOC_LEFT, &type_float, &type_integer, &type_integer}, - {7, "<<", "LSHIFT_FI", PC_SHIFT, ASSOC_LEFT, &type_float, &type_integer, &type_integer}, + {7, "^", "BITXOR_F", PC_BITXOR, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {7, ">>", "RSHIFT_F", PC_SHIFT, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {7, "<<", "LSHIFT_F", PC_SHIFT, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {7, ">>", "RSHIFT_IF", PC_SHIFT, ASSOC_LEFT, &type_integer, &type_float, &type_integer, OPF_STD}, + {7, "<<", "LSHIFT_IF", PC_SHIFT, ASSOC_LEFT, &type_integer, &type_float, &type_integer, OPF_STD}, + {7, ">>", "RSHIFT_FI", PC_SHIFT, ASSOC_LEFT, &type_float, &type_integer, &type_integer, OPF_STD}, + {7, "<<", "LSHIFT_FI", PC_SHIFT, ASSOC_LEFT, &type_float, &type_integer, &type_integer, OPF_STD}, - {7, "&&", "AND_ANY", PC_LOGICAND, ASSOC_LEFT, &type_variant, &type_variant, &type_float}, - {7, "||", "OR_ANY", PC_LOGICOR, ASSOC_LEFT, &type_variant, &type_variant, &type_float}, + {7, "&&", "AND_ANY", PC_LOGICAND, ASSOC_LEFT, &type_variant, &type_variant, &type_float, OPF_STD}, + {7, "||", "OR_ANY", PC_LOGICOR, ASSOC_LEFT, &type_variant, &type_variant, &type_float, OPF_STD}, - {7, "+", "ADD_EI", PC_ADDSUB, ASSOC_LEFT, &type_entity, &type_integer, &type_entity}, - {7, "+", "ADD_EF", PC_ADDSUB, ASSOC_LEFT, &type_entity, &type_float, &type_entity}, - {7, "-", "SUB_EI", PC_ADDSUB, ASSOC_LEFT, &type_entity, &type_integer, &type_entity}, - {7, "-", "SUB_EF", PC_ADDSUB, ASSOC_LEFT, &type_entity, &type_float, &type_entity}, + {7, "+", "ADD_EI", PC_ADDSUB, ASSOC_LEFT, &type_entity, &type_integer, &type_entity, OPF_STD}, + {7, "+", "ADD_EF", PC_ADDSUB, ASSOC_LEFT, &type_entity, &type_float, &type_entity, OPF_STD}, + {7, "-", "SUB_EI", PC_ADDSUB, ASSOC_LEFT, &type_entity, &type_integer, &type_entity, OPF_STD}, + {7, "-", "SUB_EF", PC_ADDSUB, ASSOC_LEFT, &type_entity, &type_float, &type_entity, OPF_STD}, - {7, "&", "BITAND_V", PC_BITAND, ASSOC_LEFT, &type_vector, &type_vector, &type_vector}, - {7, "|", "BITOR_V", PC_BITOR, ASSOC_LEFT, &type_vector, &type_vector, &type_vector}, - {7, "~", "BITNOT_V", PC_UNARY, ASSOC_LEFT, &type_vector, &type_void, &type_vector}, - {7, "^", "BITXOR_V", PC_BITXOR, ASSOC_LEFT, &type_vector, &type_vector, &type_vector}, + {7, "&", "BITAND_V", PC_BITAND, ASSOC_LEFT, &type_vector, &type_vector, &type_vector, OPF_STD}, + {7, "|", "BITOR_V", PC_BITOR, ASSOC_LEFT, &type_vector, &type_vector, &type_vector, OPF_STD}, + {7, "~", "BITNOT_V", PC_UNARY, ASSOC_LEFT, &type_vector, &type_void, &type_vector, OPF_STD}, + {7, "^", "BITXOR_V", PC_BITXOR, ASSOC_LEFT, &type_vector, &type_vector, &type_vector, OPF_STD}, - {7, "*^", "POW_F", PC_MULDIV, ASSOC_LEFT, &type_float, &type_float, &type_float}, - {7, "><", "CROSS_V", PC_MULDIV, ASSOC_LEFT, &type_vector, &type_vector, &type_vector}, + {7, "*^", "POW_F", PC_MULDIV, ASSOC_LEFT, &type_float, &type_float, &type_float, OPF_STD}, + {7, "><", "CROSS_V", PC_MULDIV, ASSOC_LEFT, &type_vector, &type_vector, &type_vector, OPF_STD}, - {7, "==", "EQ_FLD", PC_EQUALITY, ASSOC_LEFT, &type_field, &type_field, &type_float}, - {7, "!=", "NE_FLD", PC_EQUALITY, ASSOC_LEFT, &type_field, &type_field, &type_float}, + {7, "==", "EQ_FLD", PC_EQUALITY, ASSOC_LEFT, &type_field, &type_field, &type_float, OPF_STD}, + {7, "!=", "NE_FLD", PC_EQUALITY, ASSOC_LEFT, &type_field, &type_field, &type_float, OPF_STD}, + + {0, NULL, "OPD_GOTO_FORSTART"}, + {0, NULL, "OPD_GOTO_WHILE1"}, {0, NULL} }; @@ -14773,33 +14776,35 @@ void QCC_PR_ParseDefs (char *classname, pbool fatal) if (QCC_PR_CheckToken("]")) { //FIXME: preprocessor will hate this with a passion. - QCC_PR_Expect("="); - QCC_PR_Expect("{"); - arraysize++; - depth = 1; - while(1) + if (QCC_PR_CheckToken("=")) { - if(pr_token_type == tt_eof) + QCC_PR_Expect("{"); + arraysize++; + depth = 1; + while(1) { - QCC_PR_ParseError (ERR_EOF, "EOF inside definition of %s", name); - break; - } - else if (depth == 1 && QCC_PR_CheckToken(",")) - { - if (QCC_PR_CheckToken("}")) + if(pr_token_type == tt_eof) + { + QCC_PR_ParseError (ERR_EOF, "EOF inside definition of %s", name); break; - arraysize++; + } + else if (depth == 1 && QCC_PR_CheckToken(",")) + { + if (QCC_PR_CheckToken("}")) + break; + arraysize++; + } + else if (QCC_PR_CheckToken("{") || QCC_PR_CheckToken("[")) + depth++; + else if (QCC_PR_CheckToken("}") || QCC_PR_CheckToken("]")) + { + depth--; + if (depth == 0) + break; + } + else + QCC_PR_Lex(); } - else if (QCC_PR_CheckToken("{") || QCC_PR_CheckToken("[")) - depth++; - else if (QCC_PR_CheckToken("}") || QCC_PR_CheckToken("]")) - { - depth--; - if (depth == 0) - break; - } - else - QCC_PR_Lex(); } pr_file_p = oldprfile; pr_source_line = oldline; @@ -14866,13 +14871,8 @@ void QCC_PR_ParseDefs (char *classname, pbool fatal) gd_flags = 0; if (isstatic) gd_flags |= GDF_STATIC; - if (isconstant) - gd_flags |= GDF_CONST; - if (type->type == ev_function && !isvar && !pr_scope) - gd_flags |= GDF_CONST; - if (type->type == ev_field && !isvar && !pr_scope) - gd_flags |= GDF_CONST; - + if (isconstant || (!isvar && !pr_scope && ((isinitialised && !flag_assumevar) || type->type == ev_function || type->type == ev_field))) + gd_flags |= GDF_CONST; //initialised things are assumed to be consts, unless assumevar is specified. functions and fields are always assumed to be consts even when not initialised. nothing is assumed const at local scope. if (!nosave) gd_flags |= GDF_SAVED; if (allowinline) @@ -14965,6 +14965,7 @@ void QCC_PR_ParseDefs (char *classname, pbool fatal) } else if (isinitialised) //this is an initialisation (or a function) { + pbool isconst; QCC_type_t *parentclass; if (aliasof) QCC_PR_ParseError (ERR_SHAREDINITIALISED, "alias %s may not be initialised", name); @@ -15027,9 +15028,15 @@ void QCC_PR_ParseDefs (char *classname, pbool fatal) parentclass = pr_classtype; pr_classtype = defclass?defclass:pr_classtype; if (flag_assumevar) - def->constant = isconstant || (!isvar && !pr_scope && (type->type == ev_function || type->type == ev_field)); + isconst = isconstant || (!isvar && !pr_scope && (type->type == ev_function || type->type == ev_field)); else - def->constant = (isconstant || (!isvar && !pr_scope)); + isconst = (isconstant || (!isvar && !pr_scope)); + if (isconst != def->constant) + { //we should only be optimising consts if its initialised, so it shouldn't have been read as 0 at any point so far. + QCC_PR_ParseWarning(WARN_REDECLARATIONMISMATCH, "Redeclaration of %s would change const.", def->name); + QCC_PR_ParsePrintDef(WARN_REDECLARATIONMISMATCH, def); +// def->constant = isconst; + } if (accumulate || def->accumulate) { unsigned int pif_flags = PIF_ACCUMULATE; diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 6c8d5f6e..7a4f5b52 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -10333,10 +10333,10 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"skel_get_bonerel",PF_skel_get_bonerel,0, 0, 0, 269, D("vector(float skel, float bonenum)", "Gets the bone position and orientation relative to the bone's parent. Return value is the offset, and v_forward, v_right, v_up contain the orientation.")}, // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) {"skel_get_boneabs",PF_skel_get_boneabs,0, 0, 0, 270, D("vector(float skel, float bonenum)", "Gets the bone position and orientation relative to the entity. Return value is the offset, and v_forward, v_right, v_up contain the orientation.\nUse gettaginfo for world coord+orientation.")}, // (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) {"skel_set_bone", PF_skel_set_bone, 0, 0, 0, 271, D("void(float skel, float bonenum, vector org, optional vector fwd, optional vector right, optional vector up)", "Sets a bone position relative to its parent. If the orientation arguments are not specified, v_forward+v_right+v_up are used instead.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) - {"skel_premul_bone",PF_skel_mul_bone, 0, 0, 0, 272, D("void(float skel, float bonenum, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms a single bone by a matrix. You can use makevectors to generate a rotation matrix from an angle.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) - {"skel_premul_bones",PF_skel_mul_bones, 0, 0, 0, 273, D("void(float skel, float startbone, float endbone, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms an entire consecutive range of bones by a matrix. You can use makevectors to generate a rotation matrix from an angle, but you'll probably want to divide the angle by the number of bones.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) - {"skel_postmul_bone",PF_skel_mul_bone, 0, 0, 0, 0, D("void(float skel, float bonenum, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms a single bone by a matrix. You can use makevectors to generate a rotation matrix from an angle.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) -// {"skel_postmul_bones",PF_skel_mul_bones,0, 0, 0, 0, D("void(float skel, float startbone, float endbone, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms an entire consecutive range of bones by a matrix. You can use makevectors to generate a rotation matrix from an angle, but you'll probably want to divide the angle by the number of bones.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_premul_bone",PF_skel_premul_bone,0, 0, 0, 272, D("void(float skel, float bonenum, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms a single bone by a matrix. You can use makevectors to generate a rotation matrix from an angle.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_premul_bones",PF_skel_premul_bones,0, 0, 0, 273, D("void(float skel, float startbone, float endbone, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms an entire consecutive range of bones by a matrix. You can use makevectors to generate a rotation matrix from an angle, but you'll probably want to divide the angle by the number of bones.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) + {"skel_postmul_bone",PF_skel_postmul_bone,0, 0, 0, 0, D("void(float skel, float bonenum, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms a single bone by a matrix. You can use makevectors to generate a rotation matrix from an angle.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) +// {"skel_postmul_bones",PF_skel_postmul_bones,0, 0, 0, 0, D("void(float skel, float startbone, float endbone, vector org, optional vector fwd, optional vector right, optional vector up)", "Transforms an entire consecutive range of bones by a matrix. You can use makevectors to generate a rotation matrix from an angle, but you'll probably want to divide the angle by the number of bones.")}, // (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) {"skel_copybones", PF_skel_copybones, 0, 0, 0, 274, D("void(float skeldst, float skelsrc, float startbone, float entbone)", "Copy bone data from one skeleton directly into another.")}, // (FTE_CSQC_SKELETONOBJECTS) {"skel_delete", PF_skel_delete, 0, 0, 0, 275, D("void(float skel)", "Deletes a skeletal object. The actual delete is delayed, allowing the skeletal object to be deleted in an entity's predraw function yet still be valid by the time the addentity+renderscene builtins need it. Also uninstanciates any ragdoll currently in effect on the skeletal object.")}, // (FTE_CSQC_SKELETONOBJECTS) {"frameforname", PF_frameforname, 0, 0, 0, 276, D("float(float modidx, string framename)", "Looks up a framegroup from a model by name, avoiding the need for hardcoding. Returns -1 on error.")},// (FTE_CSQC_SKELETONOBJECTS) diff --git a/engine/shaders/glsl/lpp_depthnorm.glsl b/engine/shaders/glsl/lpp_depthnorm.glsl index 0762d9f9..6330086b 100644 --- a/engine/shaders/glsl/lpp_depthnorm.glsl +++ b/engine/shaders/glsl/lpp_depthnorm.glsl @@ -67,11 +67,11 @@ void main() #endif //we need to write specular exponents if we want per-pixel control over that -//#if defined(SPECULAR) +#if defined(SPECULAR) ospec = texture2D(s_specular, tc); -//#else -// ospec = vec4(0.0, 0.0, 0.0, 0.0); -//#endif +#else + ospec = vec4(0.0, 0.0, 0.0, 0.0); +#endif gl_FragColor = vec4(onorm.xyz, ospec.a * FTE_SPECULAR_EXPONENT); } diff --git a/engine/shaders/hlsl9/terrain.hlsl b/engine/shaders/hlsl9/terrain.hlsl index 461e91b7..28b643a7 100644 --- a/engine/shaders/hlsl9/terrain.hlsl +++ b/engine/shaders/hlsl9/terrain.hlsl @@ -3,7 +3,7 @@ #include "sys/fog.h" -//FIXME: too lazy to implement this right now. +//FIXME: too lazy to implement this right now. rtlights on d3d9 are just bad right now. #undef RTLIGHT #undef PCF #undef CUBE diff --git a/engine/vk/vk_backend.c b/engine/vk/vk_backend.c index 0603ed2a..581aa44b 100644 --- a/engine/vk/vk_backend.c +++ b/engine/vk/vk_backend.c @@ -862,8 +862,8 @@ VkShaderModule VK_CreateGLSLModule(program_t *prog, const char *name, int ver, c "vec3 e_eyepos;" "float e_time;" "vec3 e_light_ambient; float epad1;" - "vec3 e_light_dir; float epad2;" - "vec3 e_light_mul; float epad3;" + "vec3 e_light_dir; float epad2;" + "vec3 e_light_mul; float epad3;" "vec4 e_lmscales[4];" "vec3 e_uppercolour; float epad4;" "vec3 e_lowercolour; float epad5;" @@ -875,11 +875,11 @@ VkShaderModule VK_CreateGLSLModule(program_t *prog, const char *name, int ver, c "layout(std140, binding=1) uniform lightblock" "{\n" "mat4 l_cubematrix;" - "vec3 l_lightposition; float lpad1;" + "vec3 l_lightposition; float lpad1;" "vec3 l_lightcolour; float lpad2;" "vec3 l_lightcolourscale; float l_lightradius;" "vec4 l_shadowmapproj;" - "vec2 l_shadowmapscale; vec2 lpad3;" + "vec2 l_shadowmapscale; vec2 lpad3;" "};\n" ; @@ -1992,21 +1992,11 @@ static void colourgen(const shaderpass_t *pass, int cnt, byte_vec4_t *srcb, avec dst[cnt][2] = pass->rgbgen_func.args[2]; } break; + case RGB_GEN_ENTITY_LIGHTING_DIFFUSE: + R_LightArrays(shaderstate.curentity, mesh->xyz_array, dst, cnt, mesh->normals_array, shaderstate.identitylighting, true); + break; case RGB_GEN_LIGHTING_DIFFUSE: - //collect lighting details for mobile entities - if (!mesh->normals_array) - { - while((cnt)--) - { - dst[cnt][0] = 1; - dst[cnt][1] = 1; - dst[cnt][2] = 1; - } - } - else - { - R_LightArrays(shaderstate.curentity, mesh->xyz_array, dst, cnt, mesh->normals_array, shaderstate.identitylighting); - } + R_LightArrays(shaderstate.curentity, mesh->xyz_array, dst, cnt, mesh->normals_array, shaderstate.identitylighting, false); break; case RGB_GEN_WAVE: { diff --git a/fteqtv/protocol.h b/fteqtv/protocol.h index 1c4b0197..6ae56134 100644 --- a/fteqtv/protocol.h +++ b/fteqtv/protocol.h @@ -1,219 +1,219 @@ - - -//limitations of the protocol -#define MAX_SERVERINFO_STRING 1024 //standard quakeworld has 512 here. -#define MAX_USERINFO 1024 //standard quakeworld has 192 here. -#define MAX_CLIENTS 32 -#define MAX_LIST 256 -#define MAX_MODELS MAX_LIST -#define MAX_SOUNDS MAX_LIST -#define MAX_ENTITIES 512 -#define MAX_STATICSOUNDS 256 -#define MAX_STATICENTITIES 128 -#define MAX_LIGHTSTYLES 64 - -#define MAX_PROXY_INBUFFER 4096 //max bytes from a downstream proxy. -#define MAX_PROXY_BUFFER (1<<17) //must be power-of-two (buffer sizes for downstream, both sv/cl) -#define PREFERRED_PROXY_BUFFER 4096 //the ammount of data we try to leave in our input buffer (must be large enough to contain any single mvd frame) - -#define ENTS_PER_FRAME 64 //max number of entities per frame (OUCH!). -#define ENTITY_FRAMES 64 //number of frames to remember for deltaing - - -#define Z_EXT_SERVERTIME (1<<3) // STAT_TIME -#define Z_EXT_STRING "8" - -//qw specific -#define PRINT_CHAT 3 -#define PRINT_HIGH 2 -#define PRINT_MEDIUM 1 -#define PRINT_LOW 0 - - -#define MAX_STATS 32 -#define STAT_HEALTH 0 -#define STAT_FRAGS 1 -#define STAT_WEAPONMODELI 2 -#define STAT_AMMO 3 -#define STAT_ARMOR 4 -#define STAT_WEAPONFRAME 5 -#define STAT_SHELLS 6 -#define STAT_NAILS 7 -#define STAT_ROCKETS 8 -#define STAT_CELLS 9 -#define STAT_ACTIVEWEAPON 10 -#define STAT_TOTALSECRETS 11 -#define STAT_TOTALMONSTERS 12 -#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret -#define STAT_MONSTERS 14 // bumped by svc_killedmonster -#define STAT_ITEMS 15 - -#define STAT_TIME 17 //A ZQ hack, sending time via a stat. - //this allows l33t engines to interpolate properly without spamming at a silly high fps. - - - - -//limits -#define NQ_PACKETS_PER_SECOND 20 -#define MAX_MSGLEN 8192 //the biggest datagram size we allow -#define MAX_NQMSGLEN 8000 //nq has large reliable packets for the connection data -#define MAX_QWMSGLEN 1450 //qw is fully split into individual packets -#define MAX_NQDATAGRAM 1024 //nq datagrams are only 1k -#define MAX_BACKBUF_SIZE 1000 //this is smaller so we don't loose too many entities when lagging - - -//NQ transport layer defines -#define NETFLAG_LENGTH_MASK 0x0000ffff -#define NETFLAG_DATA 0x00010000 -#define NETFLAG_ACK 0x00020000 -#define NETFLAG_NAK 0x00040000 -#define NETFLAG_EOM 0x00080000 -#define NETFLAG_UNRELIABLE 0x00100000 -#define NETFLAG_CTL 0x80000000 - -#define CCREQ_CONNECT 0x01 -#define CCREQ_SERVER_INFO 0x02 - -#define CCREP_ACCEPT 0x81 -#define CCREP_REJECT 0x82 -#define CCREP_SERVER_INFO 0x83 - -#define NQ_NETCHAN_GAMENAME "QUAKE" -#define NQ_NETCHAN_VERSION 3 -//end NQ specific - - - - -//the clcs sent via the udp connections -enum { - clc_bad = 0, - clc_nop = 1, - clc_disconnect = 2, //NQ only - clc_move = 3, // [[usercmd_t] - clc_stringcmd = 4, // [string] message - clc_delta = 5, // [byte] sequence number, requests delta compression of message - clc_tmove = 6, // teleport request, spectator only - clc_upload = 7 // teleport request, spectator only -}; - -//these are the clcs sent upstream via the tcp streams -enum { - qtv_clc_bad = 0, - qtv_clc_stringcmd = 1, - qtv_clc_commentarydata = 8 -}; - - - - - - -#define svc_bad 0 -#define svc_nop 1 -#define svc_disconnect 2 -#define svc_updatestat 3 // [qbyte] [qbyte] -//#define svc_version 4 // [long] server version (not used anywhere) -#define svc_nqsetview 5 // [short] entity number -#define svc_sound 6 // -#define svc_nqtime 7 // [float] server time -#define svc_print 8 // [qbyte] id [string] null terminated string -#define svc_stufftext 9 // [string] stuffed into client's console buffer - // the string should be \n terminated -#define svc_setangle 10 // [angle3] set the view angle to this absolute value - -#define svc_serverdata 11 // [long] protocol ... -#define svc_lightstyle 12 // [qbyte] [string] -#define svc_nqupdatename 13 // [qbyte] [string] -#define svc_updatefrags 14 // [qbyte] [short] -#define svc_nqclientdata 15 // -//#define svc_stopsound 16 // (not used anywhere) -#define svc_nqupdatecolors 17 // [qbyte] [qbyte] [qbyte] -#define svc_particle 18 // [vec3] -#define svc_damage 19 - -#define svc_spawnstatic 20 -//#define svc_spawnstatic2 21 (not used anywhere) -#define svc_spawnbaseline 22 - -#define svc_temp_entity 23 // variable -#define svc_setpause 24 // [qbyte] on / off -#define svc_nqsignonnum 25 // [qbyte] used for the signon sequence - -#define svc_centerprint 26 // [string] to put in center of the screen - -#define svc_killedmonster 27 -#define svc_foundsecret 28 - -#define svc_spawnstaticsound 29 // [coord3] [qbyte] samp [qbyte] vol [qbyte] aten - -#define svc_intermission 30 // [vec3_t] origin [vec3_t] angle (show scoreboard and stuff) -#define svc_finale 31 // [string] text ('congratulations blah blah') - -#define svc_cdtrack 32 // [qbyte] track -#define svc_sellscreen 33 - -//#define svc_cutscene 34 //hmm... nq only... added after qw tree splitt? (intermission without the scores) - -#define svc_smallkick 34 // set client punchangle to 2 -#define svc_bigkick 35 // set client punchangle to 4 - -#define svc_updateping 36 // [qbyte] [short] -#define svc_updateentertime 37 // [qbyte] [float] - -#define svc_updatestatlong 38 // [qbyte] [long] - -#define svc_muzzleflash 39 // [short] entity - -#define svc_updateuserinfo 40 // [qbyte] slot [long] uid - // [string] userinfo - -#define svc_download 41 // [short] size [size bytes] -#define svc_playerinfo 42 // variable -#define svc_nails 43 // [qbyte] num [48 bits] xyzpy 12 12 12 4 8 -#define svc_chokecount 44 // [qbyte] packets choked -#define svc_modellist 45 // [strings] -#define svc_soundlist 46 // [strings] -#define svc_packetentities 47 // [...] -#define svc_deltapacketentities 48 // [...] -#define svc_maxspeed 49 // maxspeed change, for prediction -#define svc_entgravity 50 // gravity change, for prediction -#define svc_setinfo 51 // setinfo on a client -#define svc_serverinfo 52 // serverinfo -#define svc_updatepl 53 // [qbyte] [qbyte] -#define svc_nails2 54 //mvd only - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8 - - - - - -#define dem_audio 0 - -#define dem_cmd 0 -#define dem_read 1 -#define dem_set 2 -#define dem_multiple 3 -#define dem_single 4 -#define dem_stats 5 -#define dem_all 6 - -#define dem_qtvdata (dem_all | (1<<4)) //special packet that contains qtv data (spectator chat, etc. clients need to parse this as soon as it is sent to them, which might or might not be awkward for them) - -#define dem_mask 7 - - -#define PROTOCOL_VERSION_NQ 15 -#define PROTOCOL_VERSION 28 - + + +//limitations of the protocol +#define MAX_SERVERINFO_STRING 1024 //standard quakeworld has 512 here. +#define MAX_USERINFO 1024 //standard quakeworld has 192 here. +#define MAX_CLIENTS 32 +#define MAX_LIST 256 +#define MAX_MODELS MAX_LIST +#define MAX_SOUNDS MAX_LIST +#define MAX_ENTITIES 512 +#define MAX_STATICSOUNDS 256 +#define MAX_STATICENTITIES 128 +#define MAX_LIGHTSTYLES 64 + +#define MAX_PROXY_INBUFFER 4096 //max bytes from a downstream proxy. +#define MAX_PROXY_BUFFER (1<<17) //must be power-of-two (buffer sizes for downstream, both sv/cl) +#define PREFERRED_PROXY_BUFFER 4096 //the ammount of data we try to leave in our input buffer (must be large enough to contain any single mvd frame) + +#define ENTS_PER_FRAME 64 //max number of entities per frame (OUCH!). +#define ENTITY_FRAMES 64 //number of frames to remember for deltaing + + +#define Z_EXT_SERVERTIME (1<<3) // STAT_TIME +#define Z_EXT_STRING "8" + +//qw specific +#define PRINT_CHAT 3 +#define PRINT_HIGH 2 +#define PRINT_MEDIUM 1 +#define PRINT_LOW 0 + + +#define MAX_STATS 32 +#define STAT_HEALTH 0 +#define STAT_FRAGS 1 +#define STAT_WEAPONMODELI 2 +#define STAT_AMMO 3 +#define STAT_ARMOR 4 +#define STAT_WEAPONFRAME 5 +#define STAT_SHELLS 6 +#define STAT_NAILS 7 +#define STAT_ROCKETS 8 +#define STAT_CELLS 9 +#define STAT_ACTIVEWEAPON 10 +#define STAT_TOTALSECRETS 11 +#define STAT_TOTALMONSTERS 12 +#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret +#define STAT_MONSTERS 14 // bumped by svc_killedmonster +#define STAT_ITEMS 15 + +#define STAT_TIME 17 //A ZQ hack, sending time via a stat. + //this allows l33t engines to interpolate properly without spamming at a silly high fps. + + + + +//limits +#define NQ_PACKETS_PER_SECOND 20 +#define MAX_MSGLEN 8192 //the biggest datagram size we allow +#define MAX_NQMSGLEN 8000 //nq has large reliable packets for the connection data +#define MAX_QWMSGLEN 1450 //qw is fully split into individual packets +#define MAX_NQDATAGRAM 1024 //nq datagrams are only 1k +#define MAX_BACKBUF_SIZE 1000 //this is smaller so we don't loose too many entities when lagging + + +//NQ transport layer defines +#define NETFLAG_LENGTH_MASK 0x0000ffff +#define NETFLAG_DATA 0x00010000 +#define NETFLAG_ACK 0x00020000 +#define NETFLAG_NAK 0x00040000 +#define NETFLAG_EOM 0x00080000 +#define NETFLAG_UNRELIABLE 0x00100000 +#define NETFLAG_CTL 0x80000000 + +#define CCREQ_CONNECT 0x01 +#define CCREQ_SERVER_INFO 0x02 + +#define CCREP_ACCEPT 0x81 +#define CCREP_REJECT 0x82 +#define CCREP_SERVER_INFO 0x83 + +#define NQ_NETCHAN_GAMENAME "QUAKE" +#define NQ_NETCHAN_VERSION 3 +//end NQ specific + + + + +//the clcs sent via the udp connections +enum { + clc_bad = 0, + clc_nop = 1, + clc_disconnect = 2, //NQ only + clc_move = 3, // [[usercmd_t] + clc_stringcmd = 4, // [string] message + clc_delta = 5, // [byte] sequence number, requests delta compression of message + clc_tmove = 6, // teleport request, spectator only + clc_upload = 7 // teleport request, spectator only +}; + +//these are the clcs sent upstream via the tcp streams +enum { + qtv_clc_bad = 0, + qtv_clc_stringcmd = 1, + qtv_clc_commentarydata = 8 +}; + + + + + + +#define svc_bad 0 +#define svc_nop 1 +#define svc_disconnect 2 +#define svc_updatestat 3 // [qbyte] [qbyte] +//#define svc_version 4 // [long] server version (not used anywhere) +#define svc_nqsetview 5 // [short] entity number +#define svc_sound 6 // +#define svc_nqtime 7 // [float] server time +#define svc_print 8 // [qbyte] id [string] null terminated string +#define svc_stufftext 9 // [string] stuffed into client's console buffer + // the string should be \n terminated +#define svc_setangle 10 // [angle3] set the view angle to this absolute value + +#define svc_serverdata 11 // [long] protocol ... +#define svc_lightstyle 12 // [qbyte] [string] +#define svc_nqupdatename 13 // [qbyte] [string] +#define svc_updatefrags 14 // [qbyte] [short] +#define svc_nqclientdata 15 // +//#define svc_stopsound 16 // (not used anywhere) +#define svc_nqupdatecolors 17 // [qbyte] [qbyte] [qbyte] +#define svc_particle 18 // [vec3] +#define svc_damage 19 + +#define svc_spawnstatic 20 +//#define svc_spawnstatic2 21 (not used anywhere) +#define svc_spawnbaseline 22 + +#define svc_temp_entity 23 // variable +#define svc_setpause 24 // [qbyte] on / off +#define svc_nqsignonnum 25 // [qbyte] used for the signon sequence + +#define svc_centerprint 26 // [string] to put in center of the screen + +#define svc_killedmonster 27 +#define svc_foundsecret 28 + +#define svc_spawnstaticsound 29 // [coord3] [qbyte] samp [qbyte] vol [qbyte] aten + +#define svc_intermission 30 // [vec3_t] origin [vec3_t] angle (show scoreboard and stuff) +#define svc_finale 31 // [string] text ('congratulations blah blah') + +#define svc_cdtrack 32 // [qbyte] track +#define svc_sellscreen 33 + +//#define svc_cutscene 34 //hmm... nq only... added after qw tree splitt? (intermission without the scores) + +#define svc_smallkick 34 // set client punchangle to 2 +#define svc_bigkick 35 // set client punchangle to 4 + +#define svc_updateping 36 // [qbyte] [short] +#define svc_updateentertime 37 // [qbyte] [float] + +#define svc_updatestatlong 38 // [qbyte] [long] + +#define svc_muzzleflash 39 // [short] entity + +#define svc_updateuserinfo 40 // [qbyte] slot [long] uid + // [string] userinfo + +#define svc_download 41 // [short] size [size bytes] +#define svc_playerinfo 42 // variable +#define svc_nails 43 // [qbyte] num [48 bits] xyzpy 12 12 12 4 8 +#define svc_chokecount 44 // [qbyte] packets choked +#define svc_modellist 45 // [strings] +#define svc_soundlist 46 // [strings] +#define svc_packetentities 47 // [...] +#define svc_deltapacketentities 48 // [...] +#define svc_maxspeed 49 // maxspeed change, for prediction +#define svc_entgravity 50 // gravity change, for prediction +#define svc_setinfo 51 // setinfo on a client +#define svc_serverinfo 52 // serverinfo +#define svc_updatepl 53 // [qbyte] [qbyte] +#define svc_nails2 54 //mvd only - [qbyte] num [52 bits] nxyzpy 8 12 12 12 4 8 + + + + + +#define dem_audio 0 + +#define dem_cmd 0 +#define dem_read 1 +#define dem_set 2 +#define dem_multiple 3 +#define dem_single 4 +#define dem_stats 5 +#define dem_all 6 + +#define dem_qtvdata (dem_all | (1<<4)) //special packet that contains qtv data (spectator chat, etc. clients need to parse this as soon as it is sent to them, which might or might not be awkward for them) + +#define dem_mask 7 + + +#define PROTOCOL_VERSION_NQ 15 +#define PROTOCOL_VERSION 28 + #define PROTOCOL_VERSION_FTE (('F'<<0) + ('T'<<8) + ('E'<<16) + ('X' << 24)) //fte extensions. #define PROTOCOL_VERSION_FTE2 (('F'<<0) + ('T'<<8) + ('E'<<16) + ('2' << 24)) //fte extensions. #define PROTOCOL_VERSION_HUFFMAN (('H'<<0) + ('U'<<8) + ('F'<<16) + ('F' << 24)) //packet compression #define PROTOCOL_VERSION_VARLENGTH (('v'<<0) + ('l'<<8) + ('e'<<16) + ('n' << 24)) //variable length handshake -#define PROTOCOL_VERSION_FRAGMENT (('F'<<0) + ('R'<<8) + ('A'<<16) + ('G' << 24)) //supports fragmentation/packets larger than 1450 - - - +#define PROTOCOL_VERSION_FRAGMENT (('F'<<0) + ('R'<<8) + ('A'<<16) + ('G' << 24)) //supports fragmentation/packets larger than 1450 + + + #define PEXT_SETVIEW 0x00000001 #define PEXT_SCALE 0x00000002 //obsoleted by PEXT2_REPLACEMENTDELTAS #define PEXT_LIGHTSTYLECOL 0x00000004 @@ -254,53 +254,53 @@ enum { #define PEXT2_MAXPLAYERS 0x00000010 //Client is able to cope with more players than 32. abs max becomes 255, due to colormap issues. #define PEXT2_REPLACEMENTDELTAS 0x00000040 //#define PEXT2_PK3DOWNLOADS 0x10000000 //retrieve a list of pk3s/pk3s/paks for downloading (with optional URL and crcs) - - -//flags on entities -#define U_ORIGIN1 (1<<9) -#define U_ORIGIN2 (1<<10) -#define U_ORIGIN3 (1<<11) -#define U_ANGLE2 (1<<12) -#define U_FRAME (1<<13) -#define U_REMOVE (1<<14) // REMOVE this entity, don't add it -#define U_MOREBITS (1<<15) - -// if MOREBITS is set, these additional flags are read in next -#define U_ANGLE1 (1<<0) -#define U_ANGLE3 (1<<1) -#define U_MODEL (1<<2) -#define U_COLORMAP (1<<3) -#define U_SKIN (1<<4) -#define U_EFFECTS (1<<5) -#define U_SOLID (1<<6) // the entity should be solid for prediction - - - - - -//flags on players -#define PF_MSEC (1<<0) -#define PF_COMMAND (1<<1) -#define PF_VELOCITY1 (1<<2) -#define PF_VELOCITY2 (1<<3) -#define PF_VELOCITY3 (1<<4) -#define PF_MODEL (1<<5) -#define PF_SKINNUM (1<<6) -#define PF_EFFECTS (1<<7) -#define PF_WEAPONFRAME (1<<8) // only sent for view player -#define PF_DEAD (1<<9) // don't block movement any more -#define PF_GIB (1<<10) // offset the view height differently - -//flags on players in mvds -#define DF_ORIGIN 1 -#define DF_ANGLES (1<<3) -#define DF_EFFECTS (1<<6) -#define DF_SKINNUM (1<<7) -#define DF_DEAD (1<<8) -#define DF_GIB (1<<9) -#define DF_WEAPONFRAME (1<<10) -#define DF_MODEL (1<<11) - - - - + + +//flags on entities +#define U_ORIGIN1 (1<<9) +#define U_ORIGIN2 (1<<10) +#define U_ORIGIN3 (1<<11) +#define U_ANGLE2 (1<<12) +#define U_FRAME (1<<13) +#define U_REMOVE (1<<14) // REMOVE this entity, don't add it +#define U_MOREBITS (1<<15) + +// if MOREBITS is set, these additional flags are read in next +#define U_ANGLE1 (1<<0) +#define U_ANGLE3 (1<<1) +#define U_MODEL (1<<2) +#define U_COLORMAP (1<<3) +#define U_SKIN (1<<4) +#define U_EFFECTS (1<<5) +#define U_SOLID (1<<6) // the entity should be solid for prediction + + + + + +//flags on players +#define PF_MSEC (1<<0) +#define PF_COMMAND (1<<1) +#define PF_VELOCITY1 (1<<2) +#define PF_VELOCITY2 (1<<3) +#define PF_VELOCITY3 (1<<4) +#define PF_MODEL (1<<5) +#define PF_SKINNUM (1<<6) +#define PF_EFFECTS (1<<7) +#define PF_WEAPONFRAME (1<<8) // only sent for view player +#define PF_DEAD (1<<9) // don't block movement any more +#define PF_GIB (1<<10) // offset the view height differently + +//flags on players in mvds +#define DF_ORIGIN 1 +#define DF_ANGLES (1<<3) +#define DF_EFFECTS (1<<6) +#define DF_SKINNUM (1<<7) +#define DF_DEAD (1<<8) +#define DF_GIB (1<<9) +#define DF_WEAPONFRAME (1<<10) +#define DF_MODEL (1<<11) + + + + diff --git a/plugins/bullet/bulletplug.cpp b/plugins/bullet/bulletplug.cpp index 653037fa..a0587a0c 100644 --- a/plugins/bullet/bulletplug.cpp +++ b/plugins/bullet/bulletplug.cpp @@ -66,11 +66,17 @@ static rbeplugfuncs_t *rbefuncs; static void World_Bullet_RunCmd(world_t *world, rbecommandqueue_t *cmd); +static cvar_t *physics_bullet_enable; +static cvar_t *physics_bullet_maxiterationsperframe; +static cvar_t *physics_bullet_framerate; +static cvar_t *pr_meshpitch; + void World_Bullet_Init(void) { - pCvar_Register("physics_bullet_enable", "1", 0, "Bullet"); - pCvar_Register("physics_bullet_maxiterationsperframe", "10", 0, "Bullet"); - pCvar_Register("physics_bullet_framerate", "60", 0, "Bullet"); + physics_bullet_enable = pCvar_GetNVFDG("physics_bullet_enable", "1", 0, "", "Bullet"); + physics_bullet_maxiterationsperframe = pCvar_GetNVFDG("physics_bullet_maxiterationsperframe", "10", 0, "FIXME: should be 1 when CCD is working properly.", "Bullet"); + physics_bullet_framerate = pCvar_GetNVFDG("physics_bullet_framerate", "60", 0, "", "Bullet"); + pr_meshpitch = pCvar_GetNVFDG("r_meshpitch", "-1", 0, "", "Bullet"); } void World_Bullet_Shutdown(void) @@ -293,38 +299,64 @@ static void World_Bullet_Frame_BodyToEntity(world_t *world, wedict_t *ed) #endif } + +static bool NegativeMeshPitch(world_t *world, wedict_t *ent) +{ + if (ent->v->modelindex) + { + model_t *model = world->Get_CModel(world, ent->v->modelindex); + if (model && (model->type == mod_alias || model->type == mod_halflife)) + return pr_meshpitch->value < 0; + return false; + } + return false; +} + +static btTransform transformFromQuake(world_t *world, wedict_t *ent) +{ + vec3_t forward, left, up; + if (NegativeMeshPitch(world, ent)) + { + vec3_t iangles = {-ent->v->angles[0], ent->v->angles[1], ent->v->angles[2]}; + rbefuncs->AngleVectors(iangles, forward, left, up); + } + else + rbefuncs->AngleVectors(ent->v->angles, forward, left, up); + VectorNegate(left, left); + + return btTransform(btMatrix3x3(forward[0], forward[1], forward[2], left[0], left[1], left[2], up[0], up[1], up[2]), btVector3(ent->v->origin[0], ent->v->origin[1], ent->v->origin[2])); +} + static void World_Bullet_Frame_JointFromEntity(world_t *world, wedict_t *ed) { -#if 0 - dJointID j = 0; - dBodyID b1 = 0; - dBodyID b2 = 0; + bulletcontext_t *rbe = (bulletcontext_t*)world->rbe; + btTypedConstraint *j = NULL; + btRigidBody *b1 = NULL; + btRigidBody *b2 = NULL; int movetype = 0; int jointtype = 0; int enemy = 0, aiment = 0; - wedict_t *o; - vec3_t origin, velocity, angles, forward, left, up, movedir; - vec_t CFM, ERP, FMax, Stop, Vel; - VectorClear(origin); - VectorClear(velocity); - VectorClear(angles); - VectorClear(movedir); + wedict_t *e1, *e2; +// vec_t CFM, ERP, FMax; + vec_t Stop, Vel; + vec3_t forward; movetype = (int)ed->v->movetype; jointtype = (int)ed->xv->jointtype; enemy = ed->v->enemy; aiment = ed->v->aiment; - VectorCopy(ed->v->origin, origin); - VectorCopy(ed->v->velocity, velocity); - VectorCopy(ed->v->angles, angles); - VectorCopy(ed->v->movedir, movedir); + btVector3 origin(ed->v->origin[0], ed->v->origin[1], ed->v->origin[2]); + btVector3 velocity(ed->v->velocity[0], ed->v->velocity[1], ed->v->velocity[2]); + btVector3 movedir(ed->v->movedir[0], ed->v->movedir[1], ed->v->movedir[2]); if(movetype == MOVETYPE_PHYSICS) jointtype = 0; // can't have both - o = (wedict_t*)PROG_TO_EDICT(world->progs, enemy); - if(o->isfree || o->ode.ode_body == 0) + e1 = (wedict_t*)PROG_TO_EDICT(world->progs, enemy); + b1 = (btRigidBody*)e1->ode.ode_body; + if(ED_ISFREE(e1) || !b1) enemy = 0; - o = (wedict_t*)PROG_TO_EDICT(world->progs, aiment); - if(o->isfree || o->ode.ode_body == 0) + e2 = (wedict_t*)PROG_TO_EDICT(world->progs, aiment); + b2 = (btRigidBody*)e2->ode.ode_body; + if(ED_ISFREE(e2) || !b2) aiment = 0; // see http://www.ode.org/old_list_archives/2006-January/017614.html // we want to set ERP? make it fps independent and work like a spring constant @@ -334,149 +366,168 @@ static void World_Bullet_Frame_JointFromEntity(world_t *world, wedict_t *ed) float K = movedir[0]; float D = movedir[1]; float R = 2.0 * D * sqrt(K); // we assume D is premultiplied by sqrt(sprungMass) - CFM = 1.0 / (world->ode.ode_step * K + R); // always > 0 - ERP = world->ode.ode_step * K * CFM; +// CFM = 1.0 / (rbe->ode_step * K + R); // always > 0 +// ERP = rbe->ode_step * K * CFM; Vel = 0; - FMax = 0; +// FMax = 0; Stop = movedir[2]; } else if(movedir[1] < 0) { - CFM = 0; - ERP = 0; +// CFM = 0; +// ERP = 0; Vel = movedir[0]; - FMax = -movedir[1]; // TODO do we need to multiply with world.physics.ode_step? - Stop = movedir[2] > 0 ? movedir[2] : dInfinity; +// FMax = -movedir[1]; // TODO do we need to multiply with world.physics.ode_step? + Stop = movedir[2] > 0 ? movedir[2] : BT_INFINITY; } else // movedir[0] > 0, movedir[1] == 0 or movedir[0] < 0, movedir[1] >= 0 { - CFM = 0; - ERP = 0; +// CFM = 0; +// ERP = 0; Vel = 0; - FMax = 0; - Stop = dInfinity; +// FMax = 0; + Stop = BT_INFINITY; } - if(jointtype == ed->ode.ode_joint_type && VectorCompare(origin, ed->ode.ode_joint_origin) && VectorCompare(velocity, ed->ode.ode_joint_velocity) && VectorCompare(angles, ed->ode.ode_joint_angles) && enemy == ed->ode.ode_joint_enemy && aiment == ed->ode.ode_joint_aiment && VectorCompare(movedir, ed->ode.ode_joint_movedir)) + if(jointtype == ed->ode.ode_joint_type && VectorCompare(origin, ed->ode.ode_joint_origin) && VectorCompare(velocity, ed->ode.ode_joint_velocity) && VectorCompare(ed->v->angles, ed->ode.ode_joint_angles) && enemy == ed->ode.ode_joint_enemy && aiment == ed->ode.ode_joint_aiment && VectorCompare(movedir, ed->ode.ode_joint_movedir)) return; // nothing to do - AngleVectorsFLU(angles, forward, left, up); - switch(jointtype) - { - case JOINTTYPE_POINT: - j = dJointCreateBall(world->ode.ode_world, 0); - break; - case JOINTTYPE_HINGE: - j = dJointCreateHinge(world->ode.ode_world, 0); - break; - case JOINTTYPE_SLIDER: - j = dJointCreateSlider(world->ode.ode_world, 0); - break; - case JOINTTYPE_UNIVERSAL: - j = dJointCreateUniversal(world->ode.ode_world, 0); - break; - case JOINTTYPE_HINGE2: - j = dJointCreateHinge2(world->ode.ode_world, 0); - break; - case JOINTTYPE_FIXED: - j = dJointCreateFixed(world->ode.ode_world, 0); - break; - case 0: - default: - // no joint - j = 0; - break; - } + if(ed->ode.ode_joint) { - //Con_Printf("deleted old joint %i\n", (int) (ed - prog->edicts)); - dJointAttach(ed->ode.ode_joint, 0, 0); - dJointDestroy(ed->ode.ode_joint); + j = (btTypedConstraint*)ed->ode.ode_joint; + rbe->dworld->removeConstraint(j); + ed->ode.ode_joint = NULL; + delete j; } - ed->ode.ode_joint = (void *) j; + if (!jointtype) + return; + + btVector3 b1org(0,0,0), b2org(0,0,0); + if(enemy) + b1org.setValue(e1->v->origin[0], e1->v->origin[1], e1->v->origin[2]); + if(aiment) + b2org.setValue(e2->v->origin[0], e2->v->origin[1], e2->v->origin[2]); + ed->ode.ode_joint_type = jointtype; ed->ode.ode_joint_enemy = enemy; ed->ode.ode_joint_aiment = aiment; VectorCopy(origin, ed->ode.ode_joint_origin); VectorCopy(velocity, ed->ode.ode_joint_velocity); - VectorCopy(angles, ed->ode.ode_joint_angles); + VectorCopy(ed->v->angles, ed->ode.ode_joint_angles); VectorCopy(movedir, ed->ode.ode_joint_movedir); - if(j) + + rbefuncs->AngleVectors(ed->v->angles, forward, NULL, NULL); + + //Con_Printf("making new joint %i\n", (int) (ed - prog->edicts)); + switch(jointtype) { - //Con_Printf("made new joint %i\n", (int) (ed - prog->edicts)); - dJointSetData(j, (void *) ed); - if(enemy) - b1 = (dBodyID)((WEDICT_NUM(world->progs, enemy))->ode.ode_body); - if(aiment) - b2 = (dBodyID)((WEDICT_NUM(world->progs, aiment))->ode.ode_body); - dJointAttach(j, b1, b2); - - switch(jointtype) + case JOINTTYPE_POINT: + j = new btPoint2PointConstraint(*b1, *b2, btVector3(b1org - origin), btVector3(b2org - origin)); + break; +/* case JOINTTYPE_HINGE: + btHingeConstraint *h = new btHingeConstraint(*b1, *b2, btVector3(b1org - origin), btVector3(b2org - origin), aa, ab, ref); + j = h; + if (h) { - case JOINTTYPE_POINT: - dJointSetBallAnchor(j, origin[0], origin[1], origin[2]); - break; - case JOINTTYPE_HINGE: - dJointSetHingeAnchor(j, origin[0], origin[1], origin[2]); - dJointSetHingeAxis(j, forward[0], forward[1], forward[2]); - dJointSetHingeParam(j, dParamFMax, FMax); - dJointSetHingeParam(j, dParamHiStop, Stop); - dJointSetHingeParam(j, dParamLoStop, -Stop); - dJointSetHingeParam(j, dParamStopCFM, CFM); - dJointSetHingeParam(j, dParamStopERP, ERP); - dJointSetHingeParam(j, dParamVel, Vel); - break; - case JOINTTYPE_SLIDER: - dJointSetSliderAxis(j, forward[0], forward[1], forward[2]); - dJointSetSliderParam(j, dParamFMax, FMax); - dJointSetSliderParam(j, dParamHiStop, Stop); - dJointSetSliderParam(j, dParamLoStop, -Stop); - dJointSetSliderParam(j, dParamStopCFM, CFM); - dJointSetSliderParam(j, dParamStopERP, ERP); - dJointSetSliderParam(j, dParamVel, Vel); - break; - case JOINTTYPE_UNIVERSAL: - dJointSetUniversalAnchor(j, origin[0], origin[1], origin[2]); - dJointSetUniversalAxis1(j, forward[0], forward[1], forward[2]); - dJointSetUniversalAxis2(j, up[0], up[1], up[2]); - dJointSetUniversalParam(j, dParamFMax, FMax); - dJointSetUniversalParam(j, dParamHiStop, Stop); - dJointSetUniversalParam(j, dParamLoStop, -Stop); - dJointSetUniversalParam(j, dParamStopCFM, CFM); - dJointSetUniversalParam(j, dParamStopERP, ERP); - dJointSetUniversalParam(j, dParamVel, Vel); - dJointSetUniversalParam(j, dParamFMax2, FMax); - dJointSetUniversalParam(j, dParamHiStop2, Stop); - dJointSetUniversalParam(j, dParamLoStop2, -Stop); - dJointSetUniversalParam(j, dParamStopCFM2, CFM); - dJointSetUniversalParam(j, dParamStopERP2, ERP); - dJointSetUniversalParam(j, dParamVel2, Vel); - break; - case JOINTTYPE_HINGE2: - dJointSetHinge2Anchor(j, origin[0], origin[1], origin[2]); - dJointSetHinge2Axis1(j, forward[0], forward[1], forward[2]); - dJointSetHinge2Axis2(j, velocity[0], velocity[1], velocity[2]); - dJointSetHinge2Param(j, dParamFMax, FMax); - dJointSetHinge2Param(j, dParamHiStop, Stop); - dJointSetHinge2Param(j, dParamLoStop, -Stop); - dJointSetHinge2Param(j, dParamStopCFM, CFM); - dJointSetHinge2Param(j, dParamStopERP, ERP); - dJointSetHinge2Param(j, dParamVel, Vel); - dJointSetHinge2Param(j, dParamFMax2, FMax); - dJointSetHinge2Param(j, dParamHiStop2, Stop); - dJointSetHinge2Param(j, dParamLoStop2, -Stop); - dJointSetHinge2Param(j, dParamStopCFM2, CFM); - dJointSetHinge2Param(j, dParamStopERP2, ERP); - dJointSetHinge2Param(j, dParamVel2, Vel); - break; - case JOINTTYPE_FIXED: - break; - case 0: - default: - break; - } -#undef SETPARAMS + h->setLimit(-Stop, Stop, softness, bias, relaxation); + h->setAxis(btVector3(forward[0], forward[1], forward[2])); +// h->dJointSetHingeParam(j, dParamFMax, FMax); +// h->dJointSetHingeParam(j, dParamHiStop, Stop); +// h->dJointSetHingeParam(j, dParamLoStop, -Stop); +// h->dJointSetHingeParam(j, dParamStopCFM, CFM); +// h->dJointSetHingeParam(j, dParamStopERP, ERP); +// h->setMotorTarget(vel); + } + break;*/ + case JOINTTYPE_SLIDER: + { + btTransform jointtransform = transformFromQuake(world, ed); + btTransform b1transform = transformFromQuake(world, e1).inverseTimes(jointtransform); + btTransform b2transform = transformFromQuake(world, e2).inverseTimes(jointtransform); + + btSliderConstraint *s = new btSliderConstraint(*b1, *b2, b1transform, b2transform, false); + j = s; + if (s) + { +// s->dJointSetSliderAxis(j, forward[0], forward[1], forward[2]); +// s->dJointSetSliderParam(j, dParamFMax, FMax); + s->setLowerLinLimit(-Stop); + s->setUpperLinLimit(Stop); + s->setLowerAngLimit(0); + s->setUpperAngLimit(0); +// s->dJointSetSliderParam(j, dParamHiStop, Stop); +// s->dJointSetSliderParam(j, dParamLoStop, -Stop); +// s->dJointSetSliderParam(j, dParamStopCFM, CFM); +// s->dJointSetSliderParam(j, dParamStopERP, ERP); +// s->setTargetLinMotorVelocity(vel); +// s->setPoweredLinMotor(true); + } + } + break; +/* case JOINTTYPE_UNIVERSAL: + btGeneric6DofConstraint + j = dJointCreateUniversal(rbe->ode_world, 0); + if (j) + { + dJointSetUniversalAnchor(j, origin[0], origin[1], origin[2]); + dJointSetUniversalAxis1(j, forward[0], forward[1], forward[2]); + dJointSetUniversalAxis2(j, up[0], up[1], up[2]); + dJointSetUniversalParam(j, dParamFMax, FMax); + dJointSetUniversalParam(j, dParamHiStop, Stop); + dJointSetUniversalParam(j, dParamLoStop, -Stop); + dJointSetUniversalParam(j, dParamStopCFM, CFM); + dJointSetUniversalParam(j, dParamStopERP, ERP); + dJointSetUniversalParam(j, dParamVel, Vel); + dJointSetUniversalParam(j, dParamFMax2, FMax); + dJointSetUniversalParam(j, dParamHiStop2, Stop); + dJointSetUniversalParam(j, dParamLoStop2, -Stop); + dJointSetUniversalParam(j, dParamStopCFM2, CFM); + dJointSetUniversalParam(j, dParamStopERP2, ERP); + dJointSetUniversalParam(j, dParamVel2, Vel); + } + break;*/ +/* case JOINTTYPE_HINGE2: + j = dJointCreateHinge2(rbe->ode_world, 0); + if (j) + { + dJointSetHinge2Anchor(j, origin[0], origin[1], origin[2]); + dJointSetHinge2Axis1(j, forward[0], forward[1], forward[2]); + dJointSetHinge2Axis2(j, velocity[0], velocity[1], velocity[2]); + dJointSetHinge2Param(j, dParamFMax, FMax); + dJointSetHinge2Param(j, dParamHiStop, Stop); + dJointSetHinge2Param(j, dParamLoStop, -Stop); + dJointSetHinge2Param(j, dParamStopCFM, CFM); + dJointSetHinge2Param(j, dParamStopERP, ERP); + dJointSetHinge2Param(j, dParamVel, Vel); + dJointSetHinge2Param(j, dParamFMax2, FMax); + dJointSetHinge2Param(j, dParamHiStop2, Stop); + dJointSetHinge2Param(j, dParamLoStop2, -Stop); + dJointSetHinge2Param(j, dParamStopCFM2, CFM); + dJointSetHinge2Param(j, dParamStopERP2, ERP); + dJointSetHinge2Param(j, dParamVel2, Vel); + } + break;*/ + case JOINTTYPE_FIXED: + { + btTransform jointtransform = transformFromQuake(world, ed); + btTransform b1transform = transformFromQuake(world, e1).inverseTimes(jointtransform); + btTransform b2transform = transformFromQuake(world, e2).inverseTimes(jointtransform); + + j = new btFixedConstraint(*b1, *b2, b1transform, b2transform); + } + break; + case 0: + default: + j = NULL; + break; + } + + ed->ode.ode_joint = (void *) j; + if (j) + { + j->setUserConstraintPtr((void *) ed); + rbe->dworld->addConstraint(j, false); } -#endif } static qboolean QDECL World_Bullet_RagMatrixToBody(rbebody_t *bodyptr, float *mat) @@ -635,7 +686,8 @@ static void QDECL World_Bullet_RagMatrixFromJoint(rbejoint_t *joint, rbejointinf return; break; } - AngleVectorsFLU(vec3_origin, mat+0, mat+4, mat+8); + rbefuncs->AngleVectors(vec3_origin, mat+0, mat+4, mat+8); + VectorNegate((mat+4), (mat+4)); */ } @@ -836,7 +888,6 @@ public: virtual void setWorldTransform(const btTransform &worldTrans) { vec3_t fwd, left, up, offset; - qboolean meshmodel; trans = worldTrans; btVector3 pos = worldTrans.getOrigin(); @@ -848,20 +899,15 @@ public: VectorMA(pos, offset[1]*-1, left, pos); VectorMA(pos, offset[2]*-1, up, edict->v->origin); - if (edict->v->modelindex) - { - model_t *model = world->Get_CModel(world, edict->v->modelindex); - if (model && (model->type == mod_alias || model->type == mod_halflife)) - meshmodel = qtrue; - else meshmodel = qfalse; - } - else meshmodel = qfalse; + rbefuncs->VectorAngles(fwd, up, edict->v->angles, (qboolean)NegativeMeshPitch(world, edict)); - rbefuncs->VectorAngles(fwd, up, edict->v->angles, meshmodel); + const btVector3 &vel = ((btRigidBody*)edict->ode.ode_body)->getLinearVelocity(); + VectorCopy(vel.m_floats, edict->v->velocity); //so it doesn't get rebuilt VectorCopy(edict->v->origin, edict->ode.ode_origin); VectorCopy(edict->v->angles, edict->ode.ode_angles); + VectorCopy(edict->v->velocity, edict->ode.ode_velocity); // World_LinkEdict(world, edict, false); @@ -1166,8 +1212,10 @@ static void World_Bullet_Frame_BodyFromEntity(world_t *world, wedict_t *ed) // body->setCenterOfMassTransform(trans); ed->ode.ode_body = (void*)body; - //continuous collision detection prefers using a sphere within the object. tbh I have no idea what values to specify. + //motion threshhold should be speed/physicsframerate. + //FIXME: recalculate... body->setCcdMotionThreshold((geomsize[0]+geomsize[1]+geomsize[2])*(4/3)); + //radius should be the body's radius body->setCcdSweptSphereRadius((geomsize[0]+geomsize[1]+geomsize[2])*(0.5/3)); ctx->dworld->addRigidBody(body, ed->xv->dimension_solid, ed->xv->dimension_hit); @@ -1547,7 +1595,7 @@ static void QDECL World_Bullet_Frame(world_t *world, double frametime, double gr ctx->dworld->setGravity(btVector3(0, 0, -gravity)); - ctx->dworld->stepSimulation(frametime, max(0, pCvar_GetFloat("physics_bullet_maxiterationsperframe")), 1/bound(1, pCvar_GetFloat("physics_bullet_framerate"), 500)); + ctx->dworld->stepSimulation(frametime, max(0, physics_bullet_maxiterationsperframe->value), 1/bound(1, physics_bullet_framerate->value, 500)); // set the tolerance for closeness of objects // dWorldSetContactSurfaceLayer(world->ode.ode_world, max(0, physics_bullet_contactsurfacelayer.value)); @@ -1652,7 +1700,7 @@ static void QDECL World_Bullet_Start(world_t *world) if (world->rbe) return; //no thanks, we already have one. somehow. - if (!pCvar_GetFloat("physics_bullet_enable")) + if (!physics_bullet_enable->value) return; ctx = (struct bulletcontext_s*)BZ_Malloc(sizeof(*ctx));