X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=prvm_cmds.c;h=73d0a89a6ad8c1d22a9056df437debe32c15827c;hb=9f495bdf548c013b532771805fd24717ecf71fa5;hp=c9f5527966a790c4425a674193fe66484edfae6a;hpb=a57871c2f86386e3bed44f645aac4ef15c3024cf;p=xonotic%2Fdarkplaces.git diff --git a/prvm_cmds.c b/prvm_cmds.c index c9f55279..73d0a89a 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -17,9 +17,11 @@ #include "mdfour.h" extern cvar_t prvm_backtraceforwarnings; +#ifdef USEODE extern dllhandle_t ode_dll; +#endif -// LordHavoc: changed this to NOT use a return statement, so that it can be used in functions that must return a value +// LadyHavoc: changed this to NOT use a return statement, so that it can be used in functions that must return a value void VM_Warning(prvm_prog_t *prog, const char *fmt, ...) { va_list argptr; @@ -30,7 +32,7 @@ void VM_Warning(prvm_prog_t *prog, const char *fmt, ...) dpvsnprintf(msg,sizeof(msg),fmt,argptr); va_end(argptr); - Con_Print(msg); + Con_Warn(msg); // TODO: either add a cvar/cmd to control the state dumping or replace some of the calls with Con_Printf [9/13/2006 Black] if(prvm_backtraceforwarnings.integer && recursive != realtime) // NOTE: this compares to the time, just in case if PRVM_PrintState causes a Host_Error and keeps recursive set @@ -47,8 +49,8 @@ void VM_Warning(prvm_prog_t *prog, const char *fmt, ...) // TODO DONE: move vm_files and vm_fssearchlist to prvm_prog_t struct // TODO: move vm_files and vm_fssearchlist back [9/13/2006 Black] -// TODO: (move vm_files and vm_fssearchlist to prvm_prog_t struct again) [2007-01-23 LordHavoc] -// TODO: will this war ever end? [2007-01-23 LordHavoc] +// TODO: (move vm_files and vm_fssearchlist to prvm_prog_t struct again) [2007-01-23 LadyHavoc] +// TODO: will this war ever end? [2007-01-23 LadyHavoc] void VM_CheckEmptyString(prvm_prog_t *prog, const char *s) { @@ -82,7 +84,7 @@ void VM_GenerateFrameGroupBlend(prvm_prog_t *prog, framegroupblend_t *framegroup framegroupblend[0].lerp = 1 - framegroupblend[1].lerp - framegroupblend[2].lerp - framegroupblend[3].lerp; } -// LordHavoc: quite tempting to break apart this function to reuse the +// LadyHavoc: quite tempting to break apart this function to reuse the // duplicated code, but I suspect it is better for performance // this way void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroupblend_t *framegroupblend, const dp_model_t *model, double curtime) @@ -97,7 +99,10 @@ void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroup memset(blend, 0, MAX_FRAMEBLENDS * sizeof(*blend)); - if (!model || !model->surfmesh.isanimated) + // rpolzer: Not testing isanimated here - a model might have + // "animations" that move no vertices (but only bones), thus rendering + // may assume it's not animated while processing can't. + if (!model) { blend[0].lerp = 1; return; @@ -275,19 +280,21 @@ static qboolean checkextension(prvm_prog_t *prog, const char *name) e++; if ((e - start) == len && !strncasecmp(start, name, len)) { +#ifdef USEODE // special sheck for ODE if (!strncasecmp("DP_PHYSICS_ODE", name, 14)) { -#ifdef ODE_DYNAMIC +#ifndef LINK_TO_LIBODE return ode_dll ? true : false; #else -#ifdef ODE_STATIC +#ifdef LINK_TO_LIBODE return true; #else return false; #endif #endif } +#endif // special sheck for d0_blind_id if (!strcasecmp("DP_CRYPTO", name)) @@ -324,7 +331,7 @@ void VM_error(prvm_prog_t *prog) char string[VM_STRINGTEMP_LENGTH]; VM_VarString(prog, 0, string, sizeof(string)); - Con_Printf("======%s ERROR in %s:\n%s\n", prog->name, PRVM_GetString(prog, prog->xfunction->s_name), string); + Con_Errorf("======%s ERROR in %s:\n%s\n", prog->name, PRVM_GetString(prog, prog->xfunction->s_name), string); ed = PRVM_PROG_TO_EDICT(PRVM_allglobaledict(self)); PRVM_ED_Print(prog, ed, NULL); @@ -347,11 +354,11 @@ void VM_objerror(prvm_prog_t *prog) char string[VM_STRINGTEMP_LENGTH]; VM_VarString(prog, 0, string, sizeof(string)); - Con_Printf("======OBJECT ERROR======\n"); // , prog->name, PRVM_GetString(prog->xfunction->s_name), string); // or include them? FIXME + Con_Errorf("======OBJECT ERROR======\n"); // , prog->name, PRVM_GetString(prog->xfunction->s_name), string); // or include them? FIXME ed = PRVM_PROG_TO_EDICT(PRVM_allglobaledict(self)); PRVM_ED_Print(prog, ed, NULL); PRVM_ED_Free (prog, ed); - Con_Printf("%s OBJECT ERROR in %s:\n%s\nTip: read above for entity information\n", prog->name, PRVM_GetString(prog, prog->xfunction->s_name), string); + Con_Errorf("%s OBJECT ERROR in %s:\n%s\nTip: read above for entity information\n", prog->name, PRVM_GetString(prog, prog->xfunction->s_name), string); } /* @@ -597,7 +604,7 @@ void VM_break(prvm_prog_t *prog) /* ================= -VM_localcmd +VM_localcmd_client Sends text over to the client's execution buffer @@ -605,18 +612,36 @@ Sends text over to the client's execution buffer cmd (string, ...) ================= */ -void VM_localcmd(prvm_prog_t *prog) +void VM_localcmd_client(prvm_prog_t *prog) { char string[VM_STRINGTEMP_LENGTH]; VM_SAFEPARMCOUNTRANGE(1, 8, VM_localcmd); VM_VarString(prog, 0, string, sizeof(string)); - Cbuf_AddText(string); + Cbuf_AddText(&cmd_client, string); } -static qboolean PRVM_Cvar_ReadOk(const char *string) +/* +================= +VM_localcmd_server + +Sends text over to the server's execution buffer + +[localcmd (string, ...) or] +cmd (string, ...) +================= +*/ +void VM_localcmd_server(prvm_prog_t *prog) +{ + char string[VM_STRINGTEMP_LENGTH]; + VM_SAFEPARMCOUNTRANGE(1, 8, VM_localcmd); + VM_VarString(prog, 0, string, sizeof(string)); + Cbuf_AddText(&cmd_server, string); +} + +static qboolean PRVM_Cvar_ReadOk(prvm_prog_t *prog, const char *string) { cvar_t *cvar; - cvar = Cvar_FindVar(string); + cvar = Cvar_FindVar(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask); return ((cvar) && ((cvar->flags & CVAR_PRIVATE) == 0)); } @@ -633,7 +658,7 @@ void VM_cvar(prvm_prog_t *prog) VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar); VM_VarString(prog, 0, string, sizeof(string)); VM_CheckEmptyString(prog, string); - PRVM_G_FLOAT(OFS_RETURN) = PRVM_Cvar_ReadOk(string) ? Cvar_VariableValue(string) : 0; + PRVM_G_FLOAT(OFS_RETURN) = PRVM_Cvar_ReadOk(prog, string) ? Cvar_VariableValue(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask) : 0; } /* @@ -658,7 +683,7 @@ void VM_cvar_type(prvm_prog_t *prog) VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar); VM_VarString(prog, 0, string, sizeof(string)); VM_CheckEmptyString(prog, string); - cvar = Cvar_FindVar(string); + cvar = Cvar_FindVar(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask); if(!cvar) @@ -695,7 +720,7 @@ void VM_cvar_string(prvm_prog_t *prog) VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar_string); VM_VarString(prog, 0, string, sizeof(string)); VM_CheckEmptyString(prog, string); - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, PRVM_Cvar_ReadOk(string) ? Cvar_VariableString(string) : ""); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, PRVM_Cvar_ReadOk(prog, string) ? Cvar_VariableString(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask) : ""); } @@ -712,7 +737,7 @@ void VM_cvar_defstring(prvm_prog_t *prog) VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar_defstring); VM_VarString(prog, 0, string, sizeof(string)); VM_CheckEmptyString(prog, string); - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Cvar_VariableDefString(string)); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Cvar_VariableDefString(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask)); } /* @@ -728,7 +753,7 @@ void VM_cvar_description(prvm_prog_t *prog) VM_SAFEPARMCOUNTRANGE(1,8,VM_cvar_description); VM_VarString(prog, 0, string, sizeof(string)); VM_CheckEmptyString(prog, string); - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Cvar_VariableDescription(string)); + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, Cvar_VariableDescription(prog->console_cmd->cvars, string, prog->console_cmd->cvars_flagsmask)); } /* ================= @@ -745,7 +770,7 @@ void VM_cvar_set(prvm_prog_t *prog) VM_VarString(prog, 1, string, sizeof(string)); name = PRVM_G_STRING(OFS_PARM0); VM_CheckEmptyString(prog, name); - Cvar_Set(name, string); + Cvar_Set(prog->console_cmd->cvars, name, string); } /* @@ -1019,7 +1044,7 @@ void VM_find(prvm_prog_t *prog) f = PRVM_G_INT(OFS_PARM1); s = PRVM_G_STRING(OFS_PARM2); - // LordHavoc: apparently BloodMage does a find(world, weaponmodel, "") and + // LadyHavoc: apparently BloodMage does a find(world, weaponmodel, "") and // expects it to find all the monsters, so we must be careful to support // searching for "" @@ -1050,7 +1075,7 @@ VM_findfloat entity findentity(entity start, .entity field, entity match) ========= */ -// LordHavoc: added this for searching float, int, and entity reference fields +// LadyHavoc: added this for searching float, int, and entity reference fields void VM_findfloat(prvm_prog_t *prog) { int e; @@ -1111,7 +1136,7 @@ void VM_findchain(prvm_prog_t *prog) f = PRVM_G_INT(OFS_PARM0); s = PRVM_G_STRING(OFS_PARM1); - // LordHavoc: apparently BloodMage does a find(world, weaponmodel, "") and + // LadyHavoc: apparently BloodMage does a find(world, weaponmodel, "") and // expects it to find all the monsters, so we must be careful to support // searching for "" @@ -1142,7 +1167,7 @@ entity findchainfloat(.string field, float match) entity findchainentity(.string field, entity match) ========= */ -// LordHavoc: chained search for float, int, and entity reference fields +// LadyHavoc: chained search for float, int, and entity reference fields // entity(.string field, float match) findchainfloat = #403; void VM_findchainfloat(prvm_prog_t *prog) { @@ -1189,7 +1214,7 @@ VM_findflags entity findflags(entity start, .float field, float match) ======================== */ -// LordHavoc: search for flags in float fields +// LadyHavoc: search for flags in float fields void VM_findflags(prvm_prog_t *prog) { prvm_int_t e; @@ -1229,7 +1254,7 @@ VM_findchainflags entity findchainflags(.float field, float match) ======================== */ -// LordHavoc: chained search for flags in float fields +// LadyHavoc: chained search for flags in float fields void VM_findchainflags(prvm_prog_t *prog) { prvm_int_t i; @@ -1319,11 +1344,12 @@ coredump() */ void VM_coredump(prvm_prog_t *prog) { + cmd_state_t *cmd = cls.state == ca_dedicated ? &cmd_server : &cmd_client; VM_SAFEPARMCOUNT(0,VM_coredump); - Cbuf_AddText("prvm_edicts "); - Cbuf_AddText(prog->name); - Cbuf_AddText("\n"); + Cbuf_AddText(cmd, "prvm_edicts "); + Cbuf_AddText(cmd, prog->name); + Cbuf_AddText(cmd, "\n"); } /* @@ -1504,7 +1530,7 @@ void VM_changelevel(prvm_prog_t *prog) return; svs.changelevel_issued = true; - Cbuf_AddText(va(vabuf, sizeof(vabuf), "changelevel %s\n",PRVM_G_STRING(OFS_PARM0))); + Cbuf_AddText(&cmd_server, va(vabuf, sizeof(vabuf), "changelevel %s\n", PRVM_G_STRING(OFS_PARM0))); } /* @@ -1648,17 +1674,17 @@ void VM_registercvar(prvm_prog_t *prog) return; // first check to see if it has already been defined - if (Cvar_FindVar (name)) + if (Cvar_FindVar (prog->console_cmd->cvars, name, prog->console_cmd->cvars_flagsmask)) return; // check for overlap with a command - if (Cmd_Exists (name)) + if (Cmd_Exists(&cmd_client, name) || Cmd_Exists(&cmd_server, name)) { VM_Warning(prog, "VM_registercvar: %s is a command\n", name); return; } - Cvar_Get(name, value, flags, NULL); + Cvar_Get(prog->console_cmd->cvars, name, value, prog->console_cmd->cvars_flagsmask | flags, NULL); PRVM_G_FLOAT(OFS_RETURN) = 1; // success } @@ -1676,7 +1702,7 @@ float min(float a, float b, ...[float]) void VM_min(prvm_prog_t *prog) { VM_SAFEPARMCOUNTRANGE(2, 8, VM_min); - // LordHavoc: 3+ argument enhancement suggested by FrikaC + // LadyHavoc: 3+ argument enhancement suggested by FrikaC if (prog->argc >= 3) { int i; @@ -1702,7 +1728,7 @@ float max(float a, float b, ...[float]) void VM_max(prvm_prog_t *prog) { VM_SAFEPARMCOUNTRANGE(2, 8, VM_max); - // LordHavoc: 3+ argument enhancement suggested by FrikaC + // LadyHavoc: 3+ argument enhancement suggested by FrikaC if (prog->argc >= 3) { int i; @@ -2208,8 +2234,8 @@ void VM_strlennocol(prvm_prog_t *prog) szString = PRVM_G_STRING(OFS_PARM0); - //nCnt = COM_StringLengthNoColors(szString, 0, NULL); - nCnt = u8_COM_StringLengthNoColors(szString, 0, NULL); + //nCnt = (int)COM_StringLengthNoColors(szString, 0, NULL); + nCnt = (int)u8_COM_StringLengthNoColors(szString, 0, NULL); PRVM_G_FLOAT(OFS_RETURN) = nCnt; } @@ -2323,7 +2349,7 @@ void VM_substring(prvm_prog_t *prog) if (start < 0) // FTE_STRINGS feature { - u_slength = u8_strlen(s); + u_slength = (int)u8_strlen(s); start += u_slength; start = bound(0, start, u_slength); } @@ -2331,7 +2357,7 @@ void VM_substring(prvm_prog_t *prog) if (length < 0) // FTE_STRINGS feature { if (!u_slength) // it's not calculated when it's not needed above - u_slength = u8_strlen(s); + u_slength = (int)u8_strlen(s); length += u_slength - start + 1; } @@ -2547,7 +2573,7 @@ clientcommand(float client, string s) (for client and menu) ========= */ //void(entity e, string s) clientcommand = #440; // executes a command string as if it came from the specified client -//this function originally written by KrimZon, made shorter by LordHavoc +//this function originally written by KrimZon, made shorter by LadyHavoc void VM_clcommand (prvm_prog_t *prog) { client_t *temp_client; @@ -2564,7 +2590,7 @@ void VM_clcommand (prvm_prog_t *prog) temp_client = host_client; host_client = svs.clients + i; - Cmd_ExecuteString (PRVM_G_STRING(OFS_PARM1), src_client, true); + Cmd_ExecuteString (&cmd_serverfromclient, PRVM_G_STRING(OFS_PARM1), src_client, true); host_client = temp_client; } @@ -2577,8 +2603,8 @@ float tokenize(string s) ========= */ //float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many -//this function originally written by KrimZon, made shorter by LordHavoc -//20040203: rewritten by LordHavoc (no longer uses allocations) +//this function originally written by KrimZon, made shorter by LadyHavoc +//20040203: rewritten by LadyHavoc (no longer uses allocations) static int num_tokens = 0; static int tokens[VM_STRINGTEMP_LENGTH / 2]; static int tokens_startpos[VM_STRINGTEMP_LENGTH / 2]; @@ -2682,7 +2708,7 @@ void VM_tokenizebyseparator (prvm_prog_t *prog) if (!s[0]) continue; separators[numseparators] = s; - separatorlen[numseparators] = strlen(s); + separatorlen[numseparators] = (int)strlen(s); numseparators++; } @@ -2724,7 +2750,7 @@ void VM_tokenizebyseparator (prvm_prog_t *prog) } //string(float n) argv = #442; // returns a word from the tokenized string (returns nothing for an invalid index) -//this function originally written by KrimZon, made shorter by LordHavoc +//this function originally written by KrimZon, made shorter by LadyHavoc void VM_argv (prvm_prog_t *prog) { int token_num; @@ -2789,7 +2815,7 @@ void VM_isserver(prvm_prog_t *prog) { VM_SAFEPARMCOUNT(0,VM_serverstate); - PRVM_G_FLOAT(OFS_RETURN) = sv.active && (svs.maxclients > 1 || cls.state == ca_dedicated); + PRVM_G_FLOAT(OFS_RETURN) = sv.active; } /* @@ -3262,7 +3288,7 @@ string precache_pic(string pic) void VM_precache_pic(prvm_prog_t *prog) { const char *s; - int flags = 0; + int flags = CACHEPICFLAG_FAILONMISSING; VM_SAFEPARMCOUNTRANGE(1, 2, VM_precache_pic); @@ -3281,8 +3307,7 @@ void VM_precache_pic(prvm_prog_t *prog) flags |= CACHEPICFLAG_MIPMAP; } - // AK Draw_CachePic is supposed to always return a valid pointer - if( Draw_CachePic_Flags(s, flags)->tex == r_texture_notexture ) + if( !Draw_IsPicLoaded(Draw_CachePic_Flags(s, flags | CACHEPICFLAG_QUIET)) ) PRVM_G_INT(OFS_RETURN) = OFS_NULL; } @@ -3340,6 +3365,9 @@ void VM_drawcharacter(prvm_prog_t *prog) float sx, sy; VM_SAFEPARMCOUNT(6,VM_drawcharacter); + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + character = (char) PRVM_G_FLOAT(OFS_PARM1); if(character == 0) { @@ -3390,6 +3418,9 @@ void VM_drawstring(prvm_prog_t *prog) float sx, sy; VM_SAFEPARMCOUNTRANGE(5,6,VM_drawstring); + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + string = PRVM_G_STRING(OFS_PARM1); pos = PRVM_G_VECTOR(OFS_PARM0); scale = PRVM_G_VECTOR(OFS_PARM2); @@ -3439,6 +3470,9 @@ void VM_drawcolorcodedstring(prvm_prog_t *prog) VM_SAFEPARMCOUNTRANGE(5,6,VM_drawcolorcodedstring); + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + if (prog->argc == 6) // full 6 parms, like normal drawstring { pos = PRVM_G_VECTOR(OFS_PARM0); @@ -3724,6 +3758,9 @@ void VM_drawpic(prvm_prog_t *prog) VM_SAFEPARMCOUNTRANGE(5,6,VM_drawpic); + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + picname = PRVM_G_STRING(OFS_PARM1); VM_CheckEmptyString(prog, picname); @@ -3769,6 +3806,9 @@ void VM_drawrotpic(prvm_prog_t *prog) VM_SAFEPARMCOUNT(8,VM_drawrotpic); + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + picname = PRVM_G_STRING(OFS_PARM1); VM_CheckEmptyString(prog, picname); @@ -3815,6 +3855,9 @@ void VM_drawsubpic(prvm_prog_t *prog) VM_SAFEPARMCOUNT(8,VM_drawsubpic); + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + picname = PRVM_G_STRING(OFS_PARM2); VM_CheckEmptyString(prog, picname); @@ -3868,6 +3911,8 @@ void VM_drawfill(prvm_prog_t *prog) VM_SAFEPARMCOUNT(5,VM_drawfill); + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; pos = PRVM_G_VECTOR(OFS_PARM0); size = PRVM_G_VECTOR(OFS_PARM1); @@ -3900,6 +3945,9 @@ void VM_drawsetcliparea(prvm_prog_t *prog) float x,y,w,h; VM_SAFEPARMCOUNT(4,VM_drawsetcliparea); + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid_conwidth.integer); y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid_conheight.integer); w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid_conwidth.integer - x)); @@ -3919,6 +3967,9 @@ void VM_drawresetcliparea(prvm_prog_t *prog) { VM_SAFEPARMCOUNT(0,VM_drawresetcliparea); + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + DrawQ_ResetClipArea(); } @@ -3939,16 +3990,16 @@ void VM_getimagesize(prvm_prog_t *prog) p = PRVM_G_STRING(OFS_PARM0); VM_CheckEmptyString(prog, p); - pic = Draw_CachePic_Flags (p, CACHEPICFLAG_NOTPERSISTENT); - if( pic->tex == r_texture_notexture ) + pic = Draw_CachePic_Flags (p, CACHEPICFLAG_QUIET | CACHEPICFLAG_NOTPERSISTENT); + if (!Draw_IsPicLoaded(pic)) { PRVM_G_VECTOR(OFS_RETURN)[0] = 0; PRVM_G_VECTOR(OFS_RETURN)[1] = 0; } else { - PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width; - PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height; + PRVM_G_VECTOR(OFS_RETURN)[0] = Draw_GetPicWidth(pic); + PRVM_G_VECTOR(OFS_RETURN)[1] = Draw_GetPicHeight(pic); } PRVM_G_VECTOR(OFS_RETURN)[2] = 0; } @@ -4348,6 +4399,10 @@ void VM_drawline (prvm_prog_t *prog) unsigned char flags; VM_SAFEPARMCOUNT(6, VM_drawline); + + // polygonbegin without draw2d arg has to guess + prog->polygonbegin_guess2d = true; + width = PRVM_G_FLOAT(OFS_PARM0); c1 = PRVM_G_VECTOR(OFS_PARM1); c2 = PRVM_G_VECTOR(OFS_PARM2); @@ -4417,23 +4472,25 @@ string altstr_prepare(string) */ void VM_altstr_prepare(prvm_prog_t *prog) { - char *out; const char *instr, *in; - int size; char outstr[VM_STRINGTEMP_LENGTH]; + size_t outpos; VM_SAFEPARMCOUNT( 1, VM_altstr_prepare ); instr = PRVM_G_STRING( OFS_PARM0 ); - for( out = outstr, in = instr, size = sizeof(outstr) - 1 ; size && *in ; size--, in++, out++ ) - if( *in == '\'' ) { - *out++ = '\\'; - *out = '\''; - size--; - } else - *out = *in; - *out = 0; + for (in = instr, outpos = 0; *in && outpos < sizeof(outstr) - 1; ++in) + { + if (*in == '\'' && outpos < sizeof(outstr) - 2) + { + outstr[outpos++] = '\\'; + outstr[outpos++] = '\''; + } + else + outstr[outpos++] = *in; + } + outstr[outpos] = 0; PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, outstr ); } @@ -4629,7 +4686,7 @@ static int BufStr_SortStringsDOWN (const void *in1, const void *in2) return strncmp(b, a, stringbuffers_sortlength); } -prvm_stringbuffer_t *BufStr_FindCreateReplace (prvm_prog_t *prog, int bufindex, int flags, char *format) +prvm_stringbuffer_t *BufStr_FindCreateReplace (prvm_prog_t *prog, int bufindex, int flags, const char *format) { prvm_stringbuffer_t *stringbuffer; int i; @@ -4710,7 +4767,7 @@ void BufStr_Flush(prvm_prog_t *prog) prvm_stringbuffer_t *stringbuffer; int i, numbuffers; - numbuffers = Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray); + numbuffers = (int)Mem_ExpandableArray_IndexRange(&prog->stringbuffersarray); for (i = 0; i < numbuffers; i++) if ( (stringbuffer = (prvm_stringbuffer_t *)Mem_ExpandableArray_RecordAtIndex(&prog->stringbuffersarray, i)) ) BufStr_Del(prog, stringbuffer); @@ -5082,21 +5139,19 @@ void VM_buf_loadfile(prvm_prog_t *prog) size_t alloclen; prvm_stringbuffer_t *stringbuffer; char string[VM_STRINGTEMP_LENGTH]; - int filenum, strindex, c, end; + int strindex, c, end; const char *filename; char vabuf[1024]; + qfile_t *file; VM_SAFEPARMCOUNT(2, VM_buf_loadfile); // get file filename = PRVM_G_STRING(OFS_PARM0); - for (filenum = 0;filenum < PRVM_MAX_OPENFILES;filenum++) - if (prog->openfiles[filenum] == NULL) - break; - prog->openfiles[filenum] = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "data/%s", filename), false); - if (prog->openfiles[filenum] == NULL) - prog->openfiles[filenum] = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "%s", filename), false); - if (prog->openfiles[filenum] == NULL) + file = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "data/%s", filename), false); + if (file == NULL) + file = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "%s", filename), false); + if (file == NULL) { if (developer_extra.integer) VM_Warning(prog, "VM_buf_loadfile: failed to open file %s in %s\n", filename, prog->name); @@ -5121,7 +5176,7 @@ void VM_buf_loadfile(prvm_prog_t *prog) end = 0; for (;;) { - c = FS_Getc(prog->openfiles[filenum]); + c = FS_Getc(file); if (c == '\r' || c == '\n' || c < 0) break; if (end < VM_STRINGTEMP_LENGTH - 1) @@ -5131,9 +5186,9 @@ void VM_buf_loadfile(prvm_prog_t *prog) // remove \n following \r if (c == '\r') { - c = FS_Getc(prog->openfiles[filenum]); + c = FS_Getc(file); if (c != '\n') - FS_UnGetc(prog->openfiles[filenum], (unsigned char)c); + FS_UnGetc(file, (unsigned char)c); } // add and continue if (c >= 0 || end) @@ -5150,10 +5205,7 @@ void VM_buf_loadfile(prvm_prog_t *prog) } // close file - FS_Close(prog->openfiles[filenum]); - prog->openfiles[filenum] = NULL; - if (prog->openfiles_origin[filenum]) - PRVM_Free((char *)prog->openfiles_origin[filenum]); + FS_Close(file); PRVM_G_FLOAT(OFS_RETURN) = 1; } @@ -5228,7 +5280,7 @@ void VM_buf_writefile(prvm_prog_t *prog) { if (stringbuffer->strings[strindex]) { - if ((strlength = strlen(stringbuffer->strings[strindex]))) + if ((strlength = (int)strlen(stringbuffer->strings[strindex]))) FS_Write(prog->openfiles[filenum], stringbuffer->strings[strindex], strlength); FS_Write(prog->openfiles[filenum], "\n", 1); } @@ -5251,7 +5303,7 @@ static const char *detect_match_rule(char *pattern, int *matchrule) char *ppos, *qpos; int patternlength; - patternlength = strlen(pattern); + patternlength = (int)strlen(pattern); ppos = strchr(pattern, '*'); qpos = strchr(pattern, '?'); // has ? - pattern @@ -5334,7 +5386,7 @@ void VM_bufstr_find(prvm_prog_t *prog) char string[VM_STRINGTEMP_LENGTH]; int matchrule, matchlen, i, step; const char *match; - + VM_SAFEPARMCOUNTRANGE(3, 5, VM_bufstr_find); PRVM_G_FLOAT(OFS_RETURN) = -1; @@ -5349,7 +5401,7 @@ void VM_bufstr_find(prvm_prog_t *prog) // get pattern/rule matchrule = (int)PRVM_G_FLOAT(OFS_PARM2); - if (matchrule < 0 && matchrule > 5) + if (matchrule < 0 || matchrule > 5) { VM_Warning(prog, "VM_bufstr_find: invalid match rule %i in %s\n", matchrule, prog->name); return; @@ -5361,7 +5413,7 @@ void VM_bufstr_find(prvm_prog_t *prog) strlcpy(string, PRVM_G_STRING(OFS_PARM1), sizeof(string)); match = detect_match_rule(string, &matchrule); } - matchlen = strlen(match); + matchlen = (int)strlen(match); // find i = (prog->argc > 3) ? (int)PRVM_G_FLOAT(OFS_PARM3) : 0; @@ -5395,9 +5447,9 @@ void VM_matchpattern(prvm_prog_t *prog) // get pattern/rule matchrule = (int)PRVM_G_FLOAT(OFS_PARM2); - if (matchrule < 0 && matchrule > 5) + if (matchrule < 0 || matchrule > 5) { - VM_Warning(prog, "VM_bufstr_find: invalid match rule %i in %s\n", matchrule, prog->name); + VM_Warning(prog, "VM_matchpattern: invalid match rule %i in %s\n", matchrule, prog->name); return; } if (matchrule) @@ -5409,7 +5461,7 @@ void VM_matchpattern(prvm_prog_t *prog) } // offset - l = strlen(match); + l = (int)strlen(match); if (prog->argc > 3) s += max(0, min((unsigned int)PRVM_G_FLOAT(OFS_PARM3), strlen(s)-1)); @@ -5467,7 +5519,7 @@ void VM_buf_cvarlist(prvm_prog_t *prog) antiispattern = antipartial && (strchr(antipartial, '*') || strchr(antipartial, '?')); n = 0; - for(cvar = cvar_vars; cvar; cvar = cvar->next) + for(cvar = prog->console_cmd->cvars->vars; cvar; cvar = cvar->next) { if(len && (ispattern ? !matchpattern_with_separator(cvar->name, partial, false, "", false) : strncmp(partial, cvar->name, len))) continue; @@ -5483,7 +5535,7 @@ void VM_buf_cvarlist(prvm_prog_t *prog) stringbuffer->strings = (char **)Mem_Alloc(prog->progs_mempool, sizeof(stringbuffer->strings[0]) * stringbuffer->max_strings); n = 0; - for(cvar = cvar_vars; cvar; cvar = cvar->next) + for(cvar = prog->console_cmd->cvars->vars; cvar; cvar = cvar->next) { if(len && (ispattern ? !matchpattern_with_separator(cvar->name, partial, false, "", false) : strncmp(partial, cvar->name, len))) continue; @@ -5644,7 +5696,7 @@ void VM_strstrofs (prvm_prog_t *prog) instr = PRVM_G_STRING(OFS_PARM0); match = PRVM_G_STRING(OFS_PARM1); firstofs = (prog->argc > 2)?(int)PRVM_G_FLOAT(OFS_PARM2):0; - firstofs = u8_bytelen(instr, firstofs); + firstofs = (int)u8_bytelen(instr, firstofs); if (firstofs && (firstofs < 0 || firstofs > (int)strlen(instr))) { @@ -5667,7 +5719,7 @@ void VM_str2chr (prvm_prog_t *prog) int index; VM_SAFEPARMCOUNT(2, VM_str2chr); s = PRVM_G_STRING(OFS_PARM0); - index = u8_bytelen(s, (int)PRVM_G_FLOAT(OFS_PARM1)); + index = (int)u8_bytelen(s, (int)PRVM_G_FLOAT(OFS_PARM1)); if((unsigned)index < strlen(s)) { @@ -5797,7 +5849,7 @@ void VM_strconv (prvm_prog_t *prog) redalpha = (int) PRVM_G_FLOAT(OFS_PARM1); //0 same, 1 white, 2 red, 5 alternate, 6 alternate-alternate rednum = (int) PRVM_G_FLOAT(OFS_PARM2); //0 same, 1 white, 2 red, 3 redspecial, 4 whitespecial, 5 alternate, 6 alternate-alternate VM_VarString(prog, 3, (char *) resbuf, sizeof(resbuf)); - len = strlen((char *) resbuf); + len = (int)strlen((char *) resbuf); for (i = 0; i < len; i++, result++) //should this be done backwards? { @@ -5949,7 +6001,7 @@ void VM_digest_hex(prvm_prog_t *prog) if(!digest) digest = ""; VM_VarString(prog, 1, s, sizeof(s)); - len = strlen(s); + len = (int)strlen(s); outlen = 0; @@ -6031,11 +6083,14 @@ void VM_Cmd_Init(prvm_prog_t *prog) VM_Search_Init(prog); } +static void animatemodel_reset(prvm_prog_t *prog); + void VM_Cmd_Reset(prvm_prog_t *prog) { CL_PurgeOwner( MENUOWNER ); VM_Search_Reset(prog); VM_Files_CloseAll(prog); + animatemodel_reset(prog); } // #510 string(string input, ...) uri_escape (DP_QC_URI_ESCAPE) @@ -6128,7 +6183,7 @@ void VM_whichpack (prvm_prog_t *prog) fn = PRVM_G_STRING(OFS_PARM0); pack = FS_WhichPack(fn); - PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(prog, pack ? pack : ""); + PRVM_G_INT(OFS_RETURN) = pack ? PRVM_SetTempString(prog, pack) : 0; } typedef struct @@ -6805,7 +6860,8 @@ nolength: default: verbatim: if(o < end - 1) - *o++ = *s++; + *o++ = *s; + ++s; break; } } @@ -6827,9 +6883,8 @@ static dp_model_t *getmodel(prvm_prog_t *prog, prvm_edict_t *ed) return NULL; } -typedef struct +struct animatemodel_cache { - unsigned int progid; dp_model_t *model; frameblend_t frameblend[MAX_FRAMEBLENDS]; skeleton_t *skeleton_p; @@ -6843,61 +6898,74 @@ typedef struct float *buf_svector3f; float *buf_tvector3f; float *buf_normal3f; +}; + +static void animatemodel_reset(prvm_prog_t *prog) +{ + if (!prog->animatemodel_cache) + return; + if(prog->animatemodel_cache->buf_vertex3f) Mem_Free(prog->animatemodel_cache->buf_vertex3f); + if(prog->animatemodel_cache->buf_svector3f) Mem_Free(prog->animatemodel_cache->buf_svector3f); + if(prog->animatemodel_cache->buf_tvector3f) Mem_Free(prog->animatemodel_cache->buf_tvector3f); + if(prog->animatemodel_cache->buf_normal3f) Mem_Free(prog->animatemodel_cache->buf_normal3f); + Mem_Free(prog->animatemodel_cache); } -animatemodel_cache_t; -static animatemodel_cache_t animatemodel_cache; static void animatemodel(prvm_prog_t *prog, dp_model_t *model, prvm_edict_t *ed) { skeleton_t *skeleton; int skeletonindex = -1; qboolean need = false; + struct animatemodel_cache *animatemodel_cache; + if (!prog->animatemodel_cache) + { + prog->animatemodel_cache = (struct animatemodel_cache *)Mem_Alloc(prog->progs_mempool, sizeof(struct animatemodel_cache)); + memset(prog->animatemodel_cache, 0, sizeof(struct animatemodel_cache)); + } + animatemodel_cache = prog->animatemodel_cache; if(!(model->surfmesh.isanimated && model->AnimateVertices)) { - animatemodel_cache.data_vertex3f = model->surfmesh.data_vertex3f; - animatemodel_cache.data_svector3f = model->surfmesh.data_svector3f; - animatemodel_cache.data_tvector3f = model->surfmesh.data_tvector3f; - animatemodel_cache.data_normal3f = model->surfmesh.data_normal3f; + animatemodel_cache->data_vertex3f = model->surfmesh.data_vertex3f; + animatemodel_cache->data_svector3f = model->surfmesh.data_svector3f; + animatemodel_cache->data_tvector3f = model->surfmesh.data_tvector3f; + animatemodel_cache->data_normal3f = model->surfmesh.data_normal3f; return; } - if(animatemodel_cache.progid != prog->id) - memset(&animatemodel_cache, 0, sizeof(animatemodel_cache)); - need |= (animatemodel_cache.model != model); + need |= (animatemodel_cache->model != model); VM_GenerateFrameGroupBlend(prog, ed->priv.server->framegroupblend, ed); VM_FrameBlendFromFrameGroupBlend(ed->priv.server->frameblend, ed->priv.server->framegroupblend, model, PRVM_serverglobalfloat(time)); - need |= (memcmp(&animatemodel_cache.frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend))) != 0; + need |= (memcmp(&animatemodel_cache->frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend))) != 0; skeletonindex = (int)PRVM_gameedictfloat(ed, skeletonindex) - 1; if (!(skeletonindex >= 0 && skeletonindex < MAX_EDICTS && (skeleton = prog->skeletons[skeletonindex]) && skeleton->model->num_bones == ed->priv.server->skeleton.model->num_bones)) skeleton = NULL; - need |= (animatemodel_cache.skeleton_p != skeleton); + need |= (animatemodel_cache->skeleton_p != skeleton); if(skeleton) - need |= (memcmp(&animatemodel_cache.skeleton, skeleton, sizeof(ed->priv.server->skeleton))) != 0; + need |= (memcmp(&animatemodel_cache->skeleton, skeleton, sizeof(ed->priv.server->skeleton))) != 0; if(!need) return; - if(model->surfmesh.num_vertices > animatemodel_cache.max_vertices) - { - animatemodel_cache.max_vertices = model->surfmesh.num_vertices * 2; - if(animatemodel_cache.buf_vertex3f) Mem_Free(animatemodel_cache.buf_vertex3f); - if(animatemodel_cache.buf_svector3f) Mem_Free(animatemodel_cache.buf_svector3f); - if(animatemodel_cache.buf_tvector3f) Mem_Free(animatemodel_cache.buf_tvector3f); - if(animatemodel_cache.buf_normal3f) Mem_Free(animatemodel_cache.buf_normal3f); - animatemodel_cache.buf_vertex3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache.max_vertices); - animatemodel_cache.buf_svector3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache.max_vertices); - animatemodel_cache.buf_tvector3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache.max_vertices); - animatemodel_cache.buf_normal3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache.max_vertices); - } - animatemodel_cache.data_vertex3f = animatemodel_cache.buf_vertex3f; - animatemodel_cache.data_svector3f = animatemodel_cache.buf_svector3f; - animatemodel_cache.data_tvector3f = animatemodel_cache.buf_tvector3f; - animatemodel_cache.data_normal3f = animatemodel_cache.buf_normal3f; + if(model->surfmesh.num_vertices > animatemodel_cache->max_vertices) + { + animatemodel_cache->max_vertices = model->surfmesh.num_vertices * 2; + if(animatemodel_cache->buf_vertex3f) Mem_Free(animatemodel_cache->buf_vertex3f); + if(animatemodel_cache->buf_svector3f) Mem_Free(animatemodel_cache->buf_svector3f); + if(animatemodel_cache->buf_tvector3f) Mem_Free(animatemodel_cache->buf_tvector3f); + if(animatemodel_cache->buf_normal3f) Mem_Free(animatemodel_cache->buf_normal3f); + animatemodel_cache->buf_vertex3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache->max_vertices); + animatemodel_cache->buf_svector3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache->max_vertices); + animatemodel_cache->buf_tvector3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache->max_vertices); + animatemodel_cache->buf_normal3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache->max_vertices); + } + animatemodel_cache->data_vertex3f = animatemodel_cache->buf_vertex3f; + animatemodel_cache->data_svector3f = animatemodel_cache->buf_svector3f; + animatemodel_cache->data_tvector3f = animatemodel_cache->buf_tvector3f; + animatemodel_cache->data_normal3f = animatemodel_cache->buf_normal3f; VM_UpdateEdictSkeleton(prog, ed, model, ed->priv.server->frameblend); - model->AnimateVertices(model, ed->priv.server->frameblend, &ed->priv.server->skeleton, animatemodel_cache.data_vertex3f, animatemodel_cache.data_normal3f, animatemodel_cache.data_svector3f, animatemodel_cache.data_tvector3f); - animatemodel_cache.progid = prog->id; - animatemodel_cache.model = model; - memcpy(&animatemodel_cache.frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend)); - animatemodel_cache.skeleton_p = skeleton; + model->AnimateVertices(model, ed->priv.server->frameblend, &ed->priv.server->skeleton, animatemodel_cache->data_vertex3f, animatemodel_cache->data_normal3f, animatemodel_cache->data_svector3f, animatemodel_cache->data_tvector3f); + animatemodel_cache->model = model; + memcpy(&animatemodel_cache->frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend)); + animatemodel_cache->skeleton_p = skeleton; if(skeleton) - memcpy(&animatemodel_cache.skeleton, skeleton, sizeof(ed->priv.server->skeleton)); + memcpy(&animatemodel_cache->skeleton, skeleton, sizeof(ed->priv.server->skeleton)); } static void getmatrix(prvm_prog_t *prog, prvm_edict_t *ed, matrix4x4_t *out) @@ -6953,9 +7021,9 @@ static void clippointtosurface(prvm_prog_t *prog, prvm_edict_t *ed, dp_model_t * { // clip original point to each triangle of the surface and find the // triangle that is closest - v[0] = animatemodel_cache.data_vertex3f + e[0] * 3; - v[1] = animatemodel_cache.data_vertex3f + e[1] * 3; - v[2] = animatemodel_cache.data_vertex3f + e[2] * 3; + v[0] = prog->animatemodel_cache->data_vertex3f + e[0] * 3; + v[1] = prog->animatemodel_cache->data_vertex3f + e[1] * 3; + v[2] = prog->animatemodel_cache->data_vertex3f + e[2] * 3; TriangleNormal(v[0], v[1], v[2], facenormal); VectorNormalize(facenormal); offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal); @@ -7020,7 +7088,7 @@ void VM_getsurfacepoint(prvm_prog_t *prog) if (pointnum < 0 || pointnum >= surface->num_vertices) return; animatemodel(prog, model, ed); - applytransform_forward(prog, &(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + applytransform_forward(prog, &(prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); } //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486; @@ -7055,22 +7123,22 @@ void VM_getsurfacepointattribute(prvm_prog_t *prog) switch( attributetype ) { // float SPA_POSITION = 0; case 0: - applytransform_forward(prog, &(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + applytransform_forward(prog, &(prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; // float SPA_S_AXIS = 1; case 1: - applytransform_forward_direction(prog, &(animatemodel_cache.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + applytransform_forward_direction(prog, &(prog->animatemodel_cache->data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; // float SPA_T_AXIS = 2; case 2: - applytransform_forward_direction(prog, &(animatemodel_cache.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + applytransform_forward_direction(prog, &(prog->animatemodel_cache->data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; // float SPA_R_AXIS = 3; // same as SPA_NORMAL case 3: - applytransform_forward_direction(prog, &(animatemodel_cache.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + applytransform_forward_direction(prog, &(prog->animatemodel_cache->data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; // float SPA_TEXCOORDS0 = 4; @@ -7115,7 +7183,7 @@ void VM_getsurfacenormal(prvm_prog_t *prog) // note: this only returns the first triangle, so it doesn't work very // well for curved surfaces or arbitrary meshes animatemodel(prog, model, PRVM_G_EDICT(OFS_PARM0)); - TriangleNormal((animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex), (animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex) + 3, (animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex) + 6, normal); + TriangleNormal((prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex), (prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex) + 3, (prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex) + 6, normal); applytransform_forward_normal(prog, normal, PRVM_G_EDICT(OFS_PARM0), result); VectorNormalize(result); VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); @@ -7332,3 +7400,11 @@ void VM_physics_addtorque(prvm_prog_t *prog) VectorCopy(PRVM_G_VECTOR(OFS_PARM1), f.v1); VM_physics_ApplyCmd(ed, &f); } + +extern cvar_t prvm_coverage; +void VM_coverage(prvm_prog_t *prog) +{ + VM_SAFEPARMCOUNT(0, VM_coverage); + if (prog->explicit_profile[prog->xstatement]++ == 0 && (prvm_coverage.integer & 2)) + PRVM_ExplicitCoverageEvent(prog, prog->xfunction, prog->xstatement); +}