From 6c84350afd960aa30e2596a7900c916bb01b7cd5 Mon Sep 17 00:00:00 2001 From: Spoike Date: Fri, 30 May 2014 03:57:30 +0000 Subject: [PATCH] Try to fix a few issues. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4670 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/in_win.c | 2 +- engine/client/pr_csqc.c | 136 +++--- engine/client/pr_menu.c | 199 +++++++- engine/client/render.h | 1 + engine/client/sys_win.c | 66 ++- engine/client/textedit.c | 2 +- engine/client/view.c | 20 +- engine/common/com_mesh.c | 31 +- engine/common/common.c | 2 +- engine/common/log.c | 8 +- engine/common/pr_bgcmd.c | 164 ++++++- engine/common/pr_common.h | 1 + engine/common/q1bsp.c | 2 +- engine/dotnet2005/ftequake.sln | 39 ++ engine/gl/gl_backend.c | 58 ++- engine/gl/gl_draw.c | 1 + engine/gl/gl_rmain.c | 5 + engine/gl/glquake.h | 1 + engine/gl/shader.h | 32 +- engine/qclib/comprout.c | 8 +- engine/qclib/execloop.h | 2 +- engine/qclib/initlib.c | 24 +- engine/qclib/pr_edict.c | 21 +- engine/qclib/pr_exec.c | 109 ++++- engine/qclib/progsint.h | 3 +- engine/qclib/progslib.h | 4 +- engine/qclib/qcc.h | 2 + engine/qclib/qcc_pr_comp.c | 37 +- engine/qclib/qcc_pr_lex.c | 2 +- engine/qclib/qccgui.c | 846 +++++++++++++++++++++++++++------ engine/qclib/qccmain.c | 29 +- engine/server/net_preparse.c | 2 +- engine/server/pr_cmds.c | 127 ++--- engine/server/sv_ents.c | 2 +- engine/server/sv_send.c | 2 + 35 files changed, 1538 insertions(+), 452 deletions(-) diff --git a/engine/client/in_win.c b/engine/client/in_win.c index 5ae301a1f..703087933 100644 --- a/engine/client/in_win.c +++ b/engine/client/in_win.c @@ -528,7 +528,7 @@ void INS_UpdateGrabs(int fullscreen, int activeapp) grabmouse = false; //visiblity - if (grabmouse || (mousecursor_x > 0 && mousecursor_y > 0 && mousecursor_x < vid.pixelwidth && mousecursor_y < vid.pixelheight)) + if (grabmouse || (activeapp && mousecursor_x > 0 && mousecursor_y > 0 && mousecursor_x < vid.pixelwidth-1 && mousecursor_y < vid.pixelheight-1)) INS_HideMouse(); else INS_ShowMouse(); diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index ab15d126b..6609126a5 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -63,7 +63,6 @@ static qboolean csprogs_promiscuous; static unsigned int csprogs_checksum; static csqctreadstate_t *csqcthreads; qboolean csqc_resortfrags; -qboolean csqc_addcrosshair; world_t csqc_world; int csqc_playerseat; //can be negative. @@ -268,7 +267,7 @@ static void CSQC_FindGlobals(void) if (csqcg.simtime) *csqcg.simtime = cl.servertime; if (csqcg.cltime) - *csqcg.cltime = cl.time; + *csqcg.cltime = realtime; CSQC_ChangeLocalPlayer(cl_forcesplitclient.ival?(cl_forcesplitclient.ival - 1) % cl.splitclients:0); @@ -295,25 +294,6 @@ static void CSQC_FindGlobals(void) *csqcg.maxclients = cl.allocated_client_slots; } -static void QCBUILTIN PF_cs_gettime (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int timer = G_FLOAT(OFS_PARM0); - switch(timer) - { - default: - case 0: - G_FLOAT(OFS_RETURN) = realtime; - break; - case 1: - G_FLOAT(OFS_RETURN) = Sys_DoubleTime(); - break; - case 5: - G_FLOAT(OFS_RETURN) = cl.time; - break; - } -} - - //note: doesn't even have to match the clprogs.dat :) @@ -430,7 +410,7 @@ static const char *csqcmapentitydata; static qboolean csqcmapentitydataloaded; qboolean csqc_deprecated_warned; -#define csqc_deprecated(s) do {if (!csqc_deprecated_warned){Con_Printf("csqc warning: %s\n", s); csqc_deprecated_warned = true;}}while(0) +#define csqc_deprecated(s) do {if (!csqc_deprecated_warned){Con_Printf("csqc warning: %s\n", s); PR_StackTrace (prinst, false); csqc_deprecated_warned = true;}}while(0) static model_t *CSQC_GetModelForIndex(int index); @@ -517,6 +497,18 @@ static void QCBUILTIN PF_cs_remove (pubprogfuncs_t *prinst, struct globalvars_s return; } + if (!ed->entnum) + { + Con_Printf("Unable to remove the world. Try godmode."); + PR_StackTrace (prinst, false); + return; + } + if (ed->readonly) + { + Con_Printf("Entity %i is readonly.", ed->entnum); + return; + } + pe->DelinkTrailstate(&ed->trailstate); World_UnlinkEdict((wedict_t*)ed); ED_Free (prinst, (void*)ed); @@ -726,7 +718,10 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out) out->forcedshader = NULL; out->customskin = (in->skinobject<0)?-in->skinobject:in->skinobject; - out->keynum = -in->entnum; + if (in->xv->entnum) + out->keynum = in->xv->entnum; + else + out->keynum = -in->entnum; return true; } @@ -919,7 +914,7 @@ static void QCBUILTIN PF_R_DynamicLight_Get(pubprogfuncs_t *prinst, struct globa } } -static void QCBUILTIN PF_R_DynamicLight_Add(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +void QCBUILTIN PF_R_DynamicLight_Add(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { float *org = G_VECTOR(OFS_PARM0); float radius = G_FLOAT(OFS_PARM1); @@ -928,11 +923,20 @@ static void QCBUILTIN PF_R_DynamicLight_Add(pubprogfuncs_t *prinst, struct globa const char *cubemapname = (prinst->callargc > 4)?PR_GetStringOfs(prinst, OFS_PARM4):""; int pflags = (prinst->callargc > 5)?G_FLOAT(OFS_PARM5):PFLAGS_CORONA; - wedict_t *self = PROG_TO_WEDICT(prinst, *csqcg.self); + wedict_t *self; dlight_t *dl; + int dlkey; + + if (prinst == csqc_world.progs) + { + self = PROG_TO_WEDICT(prinst, *csqcg.self); + dlkey = VectorCompare(self->v->origin, org)?-self->entnum:0; + } + else + dlkey = 0; //if the org matches self, then attach it. - dl = CL_NewDlight (VectorCompare(self->v->origin, org)?-self->entnum:0, org, radius, -0.1, rgb[0], rgb[1], rgb[2]); + dl = CL_NewDlight (dlkey, org, radius, -0.1, rgb[0], rgb[1], rgb[2]); VectorCopy(csqcg.forward, dl->axis[0]); VectorCopy(csqcg.right, dl->axis[1]); @@ -1257,7 +1261,6 @@ static void QCBUILTIN PF_cs_unproject (pubprogfuncs_t *prinst, struct globalvars } } -//float CalcFov (float fov_x, float width, float height); //clear scene, and set up the default stuff. static void QCBUILTIN PF_R_ClearScene (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -1276,12 +1279,12 @@ static void QCBUILTIN PF_R_ClearScene (pubprogfuncs_t *prinst, struct globalvars V_ClearRefdef(csqc_playerview); r_refdef.drawsbar = false; //csqc defaults to no sbar. - csqc_addcrosshair = false; + r_refdef.drawcrosshair = false; V_CalcRefdef(csqc_playerview); //set up the defaults } -static void QCBUILTIN PF_R_GetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +void QCBUILTIN PF_R_GetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { viewflags parametertype = G_FLOAT(OFS_PARM0); float *r = G_VECTOR(OFS_RETURN); @@ -1293,7 +1296,8 @@ static void QCBUILTIN PF_R_GetViewFlag(pubprogfuncs_t *prinst, struct globalvars switch(parametertype) { case VF_LPLAYER: - *r = csqc_playerseat; + if (prinst == csqc_world.progs) + *r = csqc_playerseat; break; case VF_FOV: r[0] = r_refdef.fov_x; @@ -1340,12 +1344,14 @@ static void QCBUILTIN PF_R_GetViewFlag(pubprogfuncs_t *prinst, struct globalvars break; case VF_CL_VIEWANGLES_V: - VectorCopy(csqc_playerview->viewangles, r); + if (r_refdef.playerview) + VectorCopy(r_refdef.playerview->viewangles, r); break; case VF_CL_VIEWANGLES_X: case VF_CL_VIEWANGLES_Y: case VF_CL_VIEWANGLES_Z: - *r = csqc_playerview->viewangles[parametertype-VF_CL_VIEWANGLES_X]; + if (r_refdef.playerview) + *r = r_refdef.playerview->viewangles[parametertype-VF_CL_VIEWANGLES_X]; break; case VF_CARTESIAN_ANGLES: @@ -1387,7 +1393,7 @@ static void QCBUILTIN PF_R_GetViewFlag(pubprogfuncs_t *prinst, struct globalvars *r = r_refdef.drawsbar; break; case VF_DRAWCROSSHAIR: - *r = csqc_addcrosshair; + *r = r_refdef.drawcrosshair; break; case VF_PERSPECTIVE: @@ -1409,7 +1415,7 @@ static void QCBUILTIN PF_R_GetViewFlag(pubprogfuncs_t *prinst, struct globalvars } } -static void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { viewflags parametertype = G_FLOAT(OFS_PARM0); float *p = G_VECTOR(OFS_PARM1); @@ -1427,8 +1433,11 @@ static void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars switch(parametertype) { case VF_LPLAYER: - CSQC_ChangeLocalPlayer(*p); - V_CalcRefdef(csqc_playerview); //set up the default position+angles for the named player. + if (prinst == csqc_world.progs) + { + CSQC_ChangeLocalPlayer(*p); + V_CalcRefdef(csqc_playerview); //set up the default position+angles for the named player. + } break; case VF_VIEWENTITY: //switches over EXTERNALMODEL flags and clears WEAPONMODEL flagged entities. @@ -1464,11 +1473,13 @@ static void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars case VF_ORIGIN: VectorCopy(p, r_refdef.vieworg); - csqc_playerview->crouch = 0; + if (r_refdef.playerview) + r_refdef.playerview->crouch = 0; break; case VF_ORIGIN_Z: - csqc_playerview->crouch = 0; + if (r_refdef.playerview) + r_refdef.playerview->crouch = 0; case VF_ORIGIN_X: case VF_ORIGIN_Y: r_refdef.vieworg[parametertype-VF_ORIGIN_X] = *p; @@ -1484,12 +1495,14 @@ static void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars break; case VF_CL_VIEWANGLES_V: - VectorCopy(p, csqc_playerview->viewangles); + if (r_refdef.playerview) + VectorCopy(p, r_refdef.playerview->viewangles); break; case VF_CL_VIEWANGLES_X: case VF_CL_VIEWANGLES_Y: case VF_CL_VIEWANGLES_Z: - csqc_playerview->viewangles[parametertype-VF_CL_VIEWANGLES_X] = *p; + if (r_refdef.playerview) + r_refdef.playerview->viewangles[parametertype-VF_CL_VIEWANGLES_X] = *p; break; case VF_CARTESIAN_ANGLES: @@ -1537,7 +1550,7 @@ static void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars r_refdef.drawsbar = !!*p; break; case VF_DRAWCROSSHAIR: - csqc_addcrosshair = *p; + r_refdef.drawcrosshair = *p; break; case VF_PERSPECTIVE: @@ -1633,7 +1646,7 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars SCR_ShowPics_Draw(); } - if (csqc_addcrosshair) + if (r_refdef.drawcrosshair) R2D_DrawCrosshair(); BE_Scissor(NULL); @@ -2418,7 +2431,7 @@ static void QCBUILTIN PF_cl_setcursormode (pubprogfuncs_t *prinst, struct global //get the input commands, and stuff them into some globals. static void QCBUILTIN PF_cs_getinputstate (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { - usercmd_t *cmd; + usercmd_t *cmd, tmp; extern usercmd_t independantphysics[MAX_SPLITS]; int f = G_FLOAT(OFS_PARM0); int seat = ((prinst->callargc>1)?G_FLOAT(OFS_PARM1):csqc_playerseat); @@ -2442,7 +2455,13 @@ static void QCBUILTIN PF_cs_getinputstate (pubprogfuncs_t *prinst, struct global cmd = &independantphysics[seat]; for (f=0 ; f<3 ; f++) cmd->angles[f] = ((int)(csqc_playerview->viewangles[f]*65536.0/360)&65535); - //FIXME: msec probably isn't right + + if (!cmd->msec) + { + tmp = *cmd; + cmd = &tmp; + CL_BaseMove (&tmp, seat, 0, 72); + } } else { @@ -3661,9 +3680,9 @@ static void CSQC_LerpStateToCSQC(lerpents_t *le, csqcedict_t *ent, qboolean nole ent->v->frame = le->newframe; ent->xv->frame1time = max(0, cl.servertime - le->newframestarttime); ent->xv->frame2 = le->oldframe; - ent->xv->frame2time = max(0, cl.servertime - le->newframestarttime); + ent->xv->frame2time = max(0, cl.servertime - le->oldframestarttime); - ent->xv->lerpfrac = bound(0, cl.servertime - le->newframestarttime, 0.1); + ent->xv->lerpfrac = bound(0, 1-(ent->xv->frame1time) / le->framelerpdeltatime, 1); if (nolerp) @@ -3758,9 +3777,9 @@ void CSQC_EntStateToCSQC(unsigned int flags, float lerptime, entity_state_t *src ent->v->solid = SOLID_NOT; ent->v->movetype = src->u.q1.pmovetype; - ent->v->velocity[0] = src->u.q1.velocity[0]; - ent->v->velocity[1] = src->u.q1.velocity[1]; - ent->v->velocity[2] = src->u.q1.velocity[2]; + ent->v->velocity[0] = src->u.q1.velocity[0] * (1/8.0); + ent->v->velocity[1] = src->u.q1.velocity[1] * (1/8.0); + ent->v->velocity[2] = src->u.q1.velocity[2] * (1/8.0); if (model) { @@ -3844,12 +3863,13 @@ qboolean CSQC_DeltaPlayer(int playernum, player_state_t *state) ent = csqcdelta_playerents[playernum]; if (!ent) + { ent = (csqcedict_t *)ED_Alloc(csqcprogs); + ent->xv->drawmask = MASK_DELTA; + } CSQC_PlayerStateToCSQC(playernum, state, ent); - ent->xv->drawmask = MASK_DELTA; - *csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)ent); pr_globals = PR_globals(csqcprogs, PR_CURRENT); G_FLOAT(OFS_PARM0) = !csqcdelta_playerents[playernum]; @@ -3936,10 +3956,12 @@ qboolean CSQC_DeltaUpdate(entity_state_t *src) if (oldent) ent = oldent; else + { ent = (csqcedict_t *)ED_Alloc(csqcprogs); + ent->xv->drawmask = MASK_DELTA; + } CSQC_EntStateToCSQC(deltaflags[src->modelindex], csqcdelta_time, src, ent); - ent->xv->drawmask = MASK_DELTA; *csqcg.self = EDICT_TO_PROG(csqcprogs, (void*)ent); @@ -4125,7 +4147,7 @@ static void QCBUILTIN PF_V_CalcRefdef(pubprogfuncs_t *prinst, struct globalvars_ V_ClearRefdef(csqc_playerview); r_refdef.drawsbar = false; //csqc defaults to no sbar. - csqc_addcrosshair = false; + r_refdef.drawcrosshair = false; VectorCopy(ent->v->origin, csqc_playerview->simorg); @@ -4656,7 +4678,7 @@ static struct { {"memptradd", PF_memptradd, 390}, {"con_getset", PF_SubConGetSet, 391}, - {"con_print", PF_SubConPrintf, 392}, + {"con_printf", PF_SubConPrintf, 392}, {"con_draw", PF_SubConDraw, 393}, {"con_input", PF_SubConInput, 394}, @@ -4841,7 +4863,7 @@ static struct { {"buf_cvarlist", PF_buf_cvarlist, 517}, {"cvar_description", PF_cvar_description, 518}, - {"gettime", PF_cs_gettime, 519}, + {"gettime", PF_gettime, 519}, {"keynumtostring_omgwtf", PF_cl_keynumtostring, 520}, {"findkeysforcommand", PF_cl_findkeysforcommand, 521}, @@ -6194,7 +6216,7 @@ void CSQC_Input_Frame(int lplayernum, usercmd_t *cmd) if (csqcg.simtime) *csqcg.simtime = cl.servertime; if (csqcg.cltime) - *csqcg.cltime = cl.time; + *csqcg.cltime = realtime; if (csqcg.clientcommandframe) *csqcg.clientcommandframe = cl.movesequence; @@ -6288,7 +6310,7 @@ void CSQC_ParseEntities(void) if (csqcg.simtime) //estimated server time *csqcg.simtime = cl.servertime; if (csqcg.cltime) //smooth client time. - *csqcg.cltime = cl.time; + *csqcg.cltime = realtime; if (csqcg.netnewtime) *csqcg.netnewtime = cl.gametime; diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 17cdf57c3..7a575e69b 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -900,7 +900,24 @@ typedef struct menuedict_s -evalc_t menuc_eval_chain; +static struct +{ + evalc_t chain; + evalc_t model; + evalc_t mins; + evalc_t maxs; + evalc_t origin; + evalc_t angles; + evalc_t skin; + evalc_t colormap; + evalc_t frame1; + evalc_t frame2; + evalc_t lerpfrac; + evalc_t frame1time; + evalc_t frame2time; + evalc_t renderflags; +} menuc_eval; +static playerview_t menuview; int menuentsize; @@ -1016,7 +1033,7 @@ void QCBUILTIN PF_nonfatalobjerror (pubprogfuncs_t *prinst, struct globalvars_s s = PF_VarString(prinst, 0, pr_globals); - PR_StackTrace(prinst); + PR_StackTrace(prinst, true); selfp = PR_FindGlobal(prinst, "self", PR_CURRENT, NULL); if (selfp && selfp->_int) @@ -1168,7 +1185,7 @@ static void QCBUILTIN PF_Remove_ (pubprogfuncs_t *prinst, struct globalvars_s *p if (ed->isfree) { Con_DPrintf("Tried removing free entity\n"); - PR_StackTrace(prinst); + PR_StackTrace(prinst, false); return; } @@ -1209,11 +1226,6 @@ void QCBUILTIN PF_menu_checkextension (pubprogfuncs_t *prinst, struct globalvars } } -void QCBUILTIN PF_gettime (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - G_FLOAT(OFS_RETURN) = *prinst->parms->gametime; -} - void QCBUILTIN PF_CL_precache_file (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { G_INT(OFS_RETURN) = G_INT(OFS_PARM0); @@ -1244,7 +1256,7 @@ void QCBUILTIN PF_menu_findchain (pubprogfuncs_t *prinst, struct globalvars_s *p if (strcmp(PR_GetString(prinst, t), s)) continue; - val = prinst->GetEdictFieldValue(prinst, (void*)ent, "chain", &menuc_eval_chain); + val = prinst->GetEdictFieldValue(prinst, (void*)ent, "chain", &menuc_eval.chain); if (val) val->edict = EDICT_TO_PROG(prinst, (void*)chain); chain = ent; @@ -1273,7 +1285,7 @@ void QCBUILTIN PF_menu_findchainfloat (pubprogfuncs_t *prinst, struct globalvars if (((float *)ent->fields)[f] != s) continue; - val = prinst->GetEdictFieldValue(prinst, (void*)ent, "chain", NULL); + val = prinst->GetEdictFieldValue(prinst, (void*)ent, "chain", &menuc_eval.chain); if (val) val->edict = EDICT_TO_PROG(prinst, (void*)chain); chain = ent; @@ -1302,7 +1314,7 @@ void QCBUILTIN PF_menu_findchainflags (pubprogfuncs_t *prinst, struct globalvars if ((int)((float *)ent->fields)[f] & s) continue; - val = prinst->GetEdictFieldValue(prinst, (void*)ent, "chain", NULL); + val = prinst->GetEdictFieldValue(prinst, (void*)ent, "chain", &menuc_eval.chain); if (val) val->edict = EDICT_TO_PROG(prinst, (void*)chain); chain = ent; @@ -1504,6 +1516,136 @@ void QCBUILTIN PF_crypto_getmyidfp(pubprogfuncs_t *prinst, struct globalvars_s * G_INT(OFS_RETURN) = 0; } +static void QCBUILTIN PF_m_precache_model(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + const char *modelname = PR_GetStringOfs(prinst, OFS_PARM0); + Mod_ForName(modelname, MLV_WARN); +} +static void QCBUILTIN PF_m_setmodel(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + menuedict_t *ent = (void*)G_EDICT(prinst, OFS_PARM0); + string_t modelname = G_INT(OFS_PARM1); //FIXME: zone it or something? + eval_t *modelval = prinst->GetEdictFieldValue(prinst, (void*)ent, "model", &menuc_eval.model); + eval_t *minsval = prinst->GetEdictFieldValue(prinst, (void*)ent, "mins", &menuc_eval.mins); + eval_t *maxsval = prinst->GetEdictFieldValue(prinst, (void*)ent, "maxs", &menuc_eval.maxs); + model_t *mod = Mod_ForName(prinst->StringToNative(prinst, modelname), MLV_WARN); + if (modelval) + modelval->string = modelname; + if (mod && minsval) + VectorCopy(mod->mins, minsval->_vector); + if (mod && maxsval) + VectorCopy(mod->maxs, maxsval->_vector); +} +//trivially basic +static void QCBUILTIN PF_m_setorigin(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + menuedict_t *ent = (void*)G_EDICT(prinst, OFS_PARM0); + float *org = G_VECTOR(OFS_PARM1); + eval_t *val = prinst->GetEdictFieldValue(prinst, (void*)ent, "origin", &menuc_eval.origin); + if (val) + VectorCopy(org, val->_vector); +} +static void QCBUILTIN PF_m_clearscene(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +// CL_DecayLights (); + +#if defined(SKELETALOBJECTS) || defined(RAGDOLLS) + skel_dodelete(prinst); +#endif + CL_ClearEntityLists(); + + V_ClearRefdef(&menuview); + r_refdef.drawsbar = false; + r_refdef.drawcrosshair = false; + V_CalcRefdef(&menuview); //set up the defaults + r_refdef.flags |= RDF_NOWORLDMODEL; +} +static qboolean CopyMenuEdictToEntity(pubprogfuncs_t *prinst, menuedict_t *in, entity_t *out) +{ + eval_t *modelval = prinst->GetEdictFieldValue(prinst, (void*)in, "model", &menuc_eval.model); + eval_t *originval = prinst->GetEdictFieldValue(prinst, (void*)in, "origin", &menuc_eval.origin); + eval_t *anglesval = prinst->GetEdictFieldValue(prinst, (void*)in, "angles", &menuc_eval.angles); + eval_t *skinval = prinst->GetEdictFieldValue(prinst, (void*)in, "skin", &menuc_eval.skin); + eval_t *frame1val = prinst->GetEdictFieldValue(prinst, (void*)in, "frame", &menuc_eval.frame1); + eval_t *frame2val = prinst->GetEdictFieldValue(prinst, (void*)in, "frame2", &menuc_eval.frame2); + eval_t *lerpfracval = prinst->GetEdictFieldValue(prinst, (void*)in, "lerpfrac", &menuc_eval.lerpfrac); + eval_t *frame1timeval = prinst->GetEdictFieldValue(prinst, (void*)in, "frame1time", &menuc_eval.frame1time); + eval_t *frame2timeval = prinst->GetEdictFieldValue(prinst, (void*)in, "frame2time", &menuc_eval.frame2time); + eval_t *colormapval = prinst->GetEdictFieldValue(prinst, (void*)in, "colormap", &menuc_eval.colormap); + eval_t *renderflagsval = prinst->GetEdictFieldValue(prinst, (void*)in, "renderflags", &menuc_eval.renderflags); + int ival; + int rflags; + + rflags = renderflagsval?renderflagsval->_float:0; + + memset(out, 0, sizeof(*out)); + if (modelval) + out->model = Mod_ForName(prinst->StringToNative(prinst, modelval->_int), MLV_WARN); + if (originval) + VectorCopy(originval->_vector, out->origin); + if (!anglesval)anglesval = (eval_t*)vec3_origin; + AngleVectors(anglesval->_vector, out->axis[0], out->axis[1], out->axis[2]); + VectorInverse(out->axis[1]); + + out->scale = 1; + out->skinnum = skinval?skinval->_float:0; + out->framestate.g[FS_REG].frame[0] = frame1val?frame1val->_float:0; + out->framestate.g[FS_REG].frame[1] = frame2val?frame2val->_float:0; + out->framestate.g[FS_REG].lerpfrac = lerpfracval?lerpfracval->_float:0; + out->framestate.g[FS_REG].frametime[0] = frame1timeval?frame1timeval->_float:0; + out->framestate.g[FS_REG].frametime[1] = frame2timeval?frame2timeval->_float:0; + + //FIXME: colourmap + ival = colormapval?colormapval->_float:0; + out->playerindex = -1; + if (ival >= 1024) + { + //DP COLORMAP extension + out->topcolour = (ival>>4) & 0x0f; + out->bottomcolour = ival & 0xf; + } +/* else if (ival > 0 && ival <= MAX_CLIENTS) + { //FIXME: tie to the current skin/topcolor/bottomcolor cvars somehow? + out->playerindex = ival - 1; + out->topcolour = cl.players[ival-1].ttopcolor; + out->bottomcolour = cl.players[ival-1].tbottomcolor; + }*/ + else + { + out->topcolour = TOP_DEFAULT; + out->bottomcolour = BOTTOM_DEFAULT; + } + + if (rflags & CSQCRF_ADDITIVE) + out->flags |= RF_ADDITIVE; + if (rflags & CSQCRF_DEPTHHACK) + out->flags |= RF_DEPTHHACK; + + if (out->model) + return true; + return false; +} +static void QCBUILTIN PF_m_addentity(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + menuedict_t *in = (void*)G_EDICT(prinst, OFS_PARM0); + entity_t ent; + if (in->isfree || in->entnum == 0) + { + Con_Printf("Tried drawing a free/removed/world entity\n"); + return; + } + + if (CopyMenuEdictToEntity(prinst, in, &ent)) + V_AddAxisEntity(&ent); +} +static void QCBUILTIN PF_m_renderscene(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + V_ApplyRefdef(); + R_RenderView(); +} +void QCBUILTIN PF_R_SetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_R_GetViewFlag(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); + static struct { char *name; builtin_t bifunc; @@ -1598,6 +1740,9 @@ static struct { {"findflags", PF_FindFlags, 87}, {"findchainflags", PF_menu_findchainflags, 88}, {"mcvar_defstring", PF_cvar_defstring, 89}, + {"setmodel", PF_m_setmodel, 90}, + {"precache_model", PF_m_precache_model, 91}, + {"setorigin", PF_m_setorigin, 92}, //gap {"abort", PF_Abort, 211}, //gap @@ -1623,7 +1768,22 @@ static struct { {"hash_getkey", PF_hash_getkey, 292}, {"hash_getcb", PF_hash_getcb, 293}, {"checkcommand", PF_checkcommand, 294}, + {"argescape", PF_argescape, 295}, //gap + {"clearscene", PF_m_clearscene, 300}, + //no addentities + {"addentity", PF_m_addentity, 302},//FIXME: needs setmodel, origin, angles, colormap(eep), frame etc, skin, + {"setproperty", PF_R_SetViewFlag, 303},//should be okay to share + {"renderscene", PF_m_renderscene, 304},//too module-specific +// {"dynamiclight_add", PF_R_DynamicLight_Add, 305},//should be okay to share + {"R_BeginPolygon", PF_R_PolygonBegin, 306},//useful for 2d stuff + {"R_PolygonVertex", PF_R_PolygonVertex, 307}, + {"R_EndPolygon", PF_R_PolygonEnd, 308}, + {"getproperty", PF_R_GetViewFlag, 309},//should be okay to share +//unproject 310 +//project 311 + + {"print_csqc", PF_print, 339}, {"keynumtostring_csqc", PF_cl_keynumtostring, 340}, {"stringtokeynum_csqc", PF_cl_stringtokeynum, 341}, @@ -1641,6 +1801,10 @@ static struct { {"memgetval", PF_memgetval, 388}, {"memsetval", PF_memsetval, 389}, {"memptradd", PF_memptradd, 390}, + {"con_getset", PF_SubConGetSet, 391}, + {"con_printf", PF_SubConPrintf, 392}, + {"con_draw", PF_SubConDraw, 393}, + {"con_input", PF_SubConInput, 394}, //gap {"buf_create", PF_buf_create, 440}, {"buf_del", PF_buf_del, 441}, @@ -1652,7 +1816,7 @@ static struct { {"bufstr_set", PF_bufstr_set, 447}, {"bufstr_add", PF_bufstr_add, 448}, {"bufstr_free", PF_bufstr_free, 449}, - //gap + //450 {"iscachedpic", PF_CL_is_cached_pic, 451}, {"precache_pic", PF_CL_precache_pic, 452}, {"free_pic", PF_CL_free_pic, 453}, @@ -1672,7 +1836,7 @@ static struct { {"drawstring", PF_CL_drawcolouredstring, 467}, {"stringwidth", PF_CL_stringwidth, 468}, {"drawsubpic", PF_CL_drawsubpic, 469}, - //gap + //470 //MERGES WITH CLIENT+SERVER BUILTIN MAPPINGS BELOW {"asin", PF_asin, 471}, {"acos", PF_acos, 472}, @@ -1686,10 +1850,10 @@ static struct { {"strtolower", PF_strtolower, 480}, {"strtoupper", PF_strtoupper, 481}, {"cvar_defstring", PF_cvar_defstring, 482}, - //gap + //483 {"strreplace", PF_strreplace, 484}, {"strireplace", PF_strireplace, 485}, - //gap + //486 {"gecko_create", PF_cs_gecko_create, 487}, {"gecko_destroy", PF_cs_gecko_destroy, 488}, {"gecko_navigate", PF_cs_gecko_navigate, 489}, @@ -1914,7 +2078,7 @@ qboolean MP_Init (void) MP_SetupBuiltins(); - memset(&menuc_eval_chain, 0, sizeof(menuc_eval_chain)); + memset(&menuc_eval, 0, sizeof(menuc_eval)); menuprogparms.progsversion = PROGSTRUCT_VERSION; @@ -1986,6 +2150,7 @@ qboolean MP_Init (void) menu_world.g.time = (float*)PR_FindGlobal(menu_world.progs, "time", 0, NULL); if (menu_world.g.time) *menu_world.g.time = Sys_DoubleTime(); + menu_world.g.frametime = (float*)PR_FindGlobal(menu_world.progs, "frametime", 0, NULL); menu_world.g.drawfont = (float*)PR_FindGlobal(menu_world.progs, "drawfont", 0, NULL); menu_world.g.drawfontscale = (float*)PR_FindGlobal(menu_world.progs, "drawfontscale", 0, NULL); @@ -2123,6 +2288,8 @@ void MP_Draw(void) menutime = Sys_DoubleTime(); if (menu_world.g.time) *menu_world.g.time = menutime; + if (menu_world.g.frametime) + *menu_world.g.frametime = host_frametime; inmenuprogs++; if (mp_draw_function) diff --git a/engine/client/render.h b/engine/client/render.h index a06270b7f..ea7c225e4 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -205,6 +205,7 @@ typedef struct float fov_x, fov_y, afov; qboolean drawsbar; + qboolean drawcrosshair; int flags; //(Q2)RDF_ flags int dirty; diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 7ef7b5bca..66caaab47 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -1988,6 +1988,8 @@ void Sys_CloseTerminal (void) // //////////////////////////// +int debuggerresume; +int debuggerresumeline; void Sys_SendKeyEvents (void) { MSG msg; @@ -2014,6 +2016,8 @@ void Sys_SendKeyEvents (void) if (ReadFile(input, text+textpos, avail, &avail, NULL)) { textpos += avail; + if (textpos > sizeof(text)-1) + Sys_Error("No."); while(1) { text[textpos] = 0; @@ -2030,7 +2034,51 @@ void Sys_SendKeyEvents (void) sys_parentheight = strtoul(Cmd_Argv(4), NULL, 0); sys_parentwindow = (HWND)(intptr_t)strtoull(Cmd_Argv(5), NULL, 16); } - Cmd_ExecuteString(text, RESTRICT_LOCAL); + else if ((!strncmp(text, "qcstep", 6) && (text[6] == 0 || text[6] == ' ')) || (!strncmp(text, "qcresume", 8) && (text[8] == 0 || text[8] == ' '))) + { + int l; + if (text[2] == 's') + { + debuggerresume = true; + l = atoi(text+7); + } + else + { + l = atoi(text+9); + debuggerresume = 2; + } + if (l) + debuggerresumeline = l; + } + else if (!strncmp(text, "qcbreakpoint ", 13)) + { + extern world_t csqc_world, menu_world; + int mode; + char *filename; + int line; + Cmd_TokenizeString(text, false, false); + mode = strtoul(Cmd_Argv(1), NULL, 0); + filename = Cmd_Argv(2); + line = strtoul(Cmd_Argv(3), NULL, 0); + //togglebreakpoint just finds the first statement (via the function table for file names) with the specified line number, and sets some unused high bit that causes it to be an invalid opcode. +#ifdef CSQC_DAT + if (csqc_world.progs && csqc_world.progs->ToggleBreak) + csqc_world.progs->ToggleBreak(csqc_world.progs, filename, line, mode); +#endif +#ifdef MENU_DAT + if (menu_world.progs && menu_world.progs->ToggleBreak) + menu_world.progs->ToggleBreak(menu_world.progs, filename, line, mode); +#endif +#ifndef CLIENTONLY + if (sv.world.progs && sv.world.progs->ToggleBreak) + sv.world.progs->ToggleBreak(sv.world.progs, filename, line, mode); +#endif + } + else + { + Cbuf_AddText(text, RESTRICT_LOCAL); + Cbuf_AddText("\n", RESTRICT_LOCAL); + } memmove(text, nl, textpos - (nl - text)); textpos -= (nl - text); } @@ -3013,10 +3061,11 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin int delay = 0; char lang[32]; char ctry[32]; + int c; /* previous instances do not exist in Win32 */ - if (hPrevInstance) - return 0; + if (hPrevInstance) + return 0; /* determine if we're on nt early, so we don't do the wrong thing when checking commandlines */ { @@ -3112,7 +3161,16 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin if (Sys_CheckUpdated()) return true; - isPlugin = !!COM_CheckParm("-plugin"); + c = COM_CheckParm("-plugin"); + if (c) + { + if (c < com_argc && !strcmp(com_argv[c+1], "qcdebug")) + isPlugin = 2; + else + isPlugin = 1; + } + else + isPlugin = 0; if (COM_CheckParm("-register_types")) { diff --git a/engine/client/textedit.c b/engine/client/textedit.c index 5c337fa7d..c46a261f9 100644 --- a/engine/client/textedit.c +++ b/engine/client/textedit.c @@ -630,7 +630,7 @@ void Editor_Key(int key, int unicode) break; case K_F6: if (editprogfuncs) - PR_StackTrace(editprogfuncs); + PR_StackTrace(editprogfuncs, 2); break; case K_F7: /*save+recompile*/ EditorSaveFile(OpenEditorFile); diff --git a/engine/client/view.c b/engine/client/view.c index 7d624b380..947af8431 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -873,14 +873,18 @@ void V_CalcGunPositionAngle (playerview_t *pv, float bob) // fudge position around to keep amount of weapon visible // roughly equal with different FOV - if (scr_viewsize.value == 110) - pv->vw_origin[2] += 1; - else if (scr_viewsize.value == 100) - pv->vw_origin[2] += 2; - else if (scr_viewsize.value == 90) - pv->vw_origin[2] += 1; - else if (scr_viewsize.value == 80) - pv->vw_origin[2] += 0.5; +//FIXME: should use y fov, not viewsize. + if (r_refdef.drawsbar) //no sbar = no viewsize cvar. + { + if (scr_viewsize.value == 110) + pv->vw_origin[2] += 1; + else if (scr_viewsize.value == 100) + pv->vw_origin[2] += 2; + else if (scr_viewsize.value == 90) + pv->vw_origin[2] += 1; + else if (scr_viewsize.value == 80) + pv->vw_origin[2] += 0.5; + } } /* diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 09a24818e..572eaf936 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -1266,6 +1266,7 @@ static int Alias_FindRawSkelData(galiasinfo_t *inf, framestate_t *fstate, skelle lerps->endbone = endbone; cbone = endbone; numbonegroups++; + lerps++; } return numbonegroups; } @@ -1366,7 +1367,7 @@ const float *Alias_GetBoneInformation(galiasinfo_t *inf, framestate_t *framestat for (; bone < endbone; bone++, out+=12, pose1+=12, pose2+=12) { for (k = 0; k < 12; k++) //please please unroll! - out[k] = pose1[k]*frac1 + frac2*pose2[k]; + out[k] = (pose1[k]*frac1) + (frac2*pose2[k]); } } break; @@ -1376,10 +1377,10 @@ const float *Alias_GetBoneInformation(galiasinfo_t *inf, framestate_t *framestat float *out = targetbuffer + bone*12; float *pose1 = lerp->pose[0] + bone*12, *pose2 = lerp->pose[1] + bone*12, *pose3 = lerp->pose[2] + bone*12; float frac1 = lerp->frac[0], frac2 = lerp->frac[1], frac3 = lerp->frac[2]; - for (; bone < endbone; bone++) + for (; bone < endbone; bone++, out+=12, pose1+=12, pose2+=12, pose3+=12) { for (k = 0; k < 12; k++) //please please unroll! - out[k] = pose1[k]*frac1 + frac2*pose2[k] + pose3[k]*frac3; + out[k] = (pose1[k]*frac1) + (frac2*pose2[k]) + (pose3[k]*frac3); } } break; @@ -1389,10 +1390,10 @@ const float *Alias_GetBoneInformation(galiasinfo_t *inf, framestate_t *framestat float *out = targetbuffer + bone*12; float *pose1 = lerp->pose[0] + bone*12, *pose2 = lerp->pose[1] + bone*12, *pose3 = lerp->pose[2] + bone*12, *pose4 = lerp->pose[3] + bone*12; float frac1 = lerp->frac[0], frac2 = lerp->frac[1], frac3 = lerp->frac[2], frac4 = lerp->frac[3]; - for (; bone < endbone; bone++) + for (; bone < endbone; bone++, out+=12, pose1+=12, pose2+=12, pose3+=12, pose4+=12) { for (k = 0; k < 12; k++) //please please unroll! - out[k] = pose1[k]*frac1 + frac2*pose2[k] + pose3[k]*frac3 + frac4*pose4[k]; + out[k] = (pose1[k]*frac1) + (frac2*pose2[k]) + (pose3[k]*frac3) + (frac4*pose4[k]); } } break; @@ -1462,7 +1463,7 @@ static void Alias_BuildSkeletalVPositionsPose(float *xyzout, skeltype_t bonetype #ifndef SERVERONLY #ifdef GLQUAKE #include "glquake.h" -static void Alias_GLDrawSkeletalBones(galiasbone_t *bones, float *bonepose, int bonecount) +static void Alias_GLDrawSkeletalBones(galiasbone_t *bones, float *bonepose, int bonecount, int basebone) { PPL_RevertToKnownState(); BE_SelectEntity(currententity); @@ -1473,7 +1474,17 @@ static void Alias_GLDrawSkeletalBones(galiasbone_t *bones, float *bonepose, int vec3_t org, dest; qglBegin(GL_LINES); - for (i = 0; i < bonecount; i++) + qglColor3f(0, 0, 1); + for (i = 0; i < basebone; i++) + { + p = bones[i].parent; + if (p < 0) + p = 0; + qglVertex3f(bonepose[i*12+3], bonepose[i*12+7], bonepose[i*12+11]); + qglVertex3f(bonepose[p*12+3], bonepose[p*12+7], bonepose[p*12+11]); + } + qglColor3f(1, 0, 0); + for (; i < bonecount; i++) { p = bones[i].parent; if (p < 0) @@ -1483,7 +1494,7 @@ static void Alias_GLDrawSkeletalBones(galiasbone_t *bones, float *bonepose, int } qglEnd(); qglColor3f(1, 1, 1); - qglBegin(GL_LINES); +/* qglBegin(GL_LINES); for (i = 0; i < bonecount; i++) { p = bones[i].parent; @@ -1515,7 +1526,7 @@ static void Alias_GLDrawSkeletalBones(galiasbone_t *bones, float *bonepose, int qglVertex3f(bonepose[p*12+3], bonepose[p*12+7], bonepose[p*12+11]); } qglEnd(); - +*/ // mesh->numindexes = 0; //don't draw this mesh, as that would obscure the bones. :( } } @@ -1712,7 +1723,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in meshcache.usebonepose = Alias_GetBoneInformation(inf, &e->framestate, meshcache.bonecachetype=SKEL_ABSOLUTE, meshcache.boneposebuffer1, meshcache.boneposebuffer2, MAX_BONES); if (qrenderer == QR_OPENGL) { - Alias_GLDrawSkeletalBones(inf->ofsbones, (float *)meshcache.usebonepose, inf->numbones); + Alias_GLDrawSkeletalBones(inf->ofsbones, (float *)meshcache.usebonepose, inf->numbones, e->framestate.g[0].endbone); } #endif } diff --git a/engine/common/common.c b/engine/common/common.c index e8e0768e1..0981df9fb 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -102,7 +102,7 @@ qboolean com_modified; // set true if using non-id files qboolean static_registered = true; // only for startup check, then set qboolean msg_suppress_1 = false; -qboolean isPlugin; +int isPlugin; //if 2, we qcdebug to external program void COM_Path_f (void); void COM_Dir_f (void); diff --git a/engine/common/log.c b/engine/common/log.c index 76fa49994..ca4daa5cd 100644 --- a/engine/common/log.c +++ b/engine/common/log.c @@ -114,8 +114,12 @@ void Log_String (logtype_t lognum, char *s) if (log_timestamps.ival) { time_t unixtime = time(NULL); - strftime(t, utf8+sizeof(utf8)-1-t, "%Y-%m-%d %H:%M:%S ", localtime(&unixtime)); - t += strlen(t); + int bufferspace = utf8+sizeof(utf8)-1-t; + if (bufferspace > 0) + { + strftime(t, bufferspace, "%Y-%m-%d %H:%M:%S ", localtime(&unixtime)); + t += strlen(t); + } } log_newline[lognum] = false; } diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index eb3e54743..e4917dacc 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -71,6 +71,124 @@ char *PF_VarString (pubprogfuncs_t *prinst, int first, struct globalvars_s *pr_g } return out; } + +extern int debuggerresume; +extern int debuggerresumeline; +extern int isPlugin; //if 2, we were invoked by a debugger, and we need to give it debug locations (and it'll feed us continue/steps/breakpoints) +static int debuggerstacky; + +#ifdef _WIN32 +#include +void INS_UpdateGrabs(int fullscreen, int activeapp); +#endif +int QCLibEditor(pubprogfuncs_t *prinst, char *filename, int line, int statement, int nump, char **parms); +void QCLoadBreakpoints(const char *vmname, const char *progsname) +{ //this asks the gui to reapply any active breakpoints and waits for them so that any spawn functions can be breakpointed properly. +#if defined(_WIN32) && !defined(SERVERONLY) + extern int isPlugin; + if (isPlugin == 2) + { + Sys_SendKeyEvents(); + debuggerresume = false; + printf("qcreloaded \"%s\" \"%s\"\n", vmname, progsname); + fflush(stdout); + INS_UpdateGrabs(false, false); + while(debuggerresume != 2) + { + Sleep(10); + Sys_SendKeyEvents(); + } + } +#endif +} +extern cvar_t pr_sourcedir; +int QDECL QCEditor (pubprogfuncs_t *prinst, char *filename, int line, int statement, int nump, char **parms) +{ +#if defined(_WIN32) && !defined(SERVERONLY) + if (isPlugin == 2) + { + if (!*filename) //don't try editing an empty line, it won't work + return line; + Sys_SendKeyEvents(); + debuggerresume = false; + debuggerresumeline = line; + printf("qcstep \"%s\":%i\n", filename, line); + fflush(stdout); + INS_UpdateGrabs(false, false); + while(!debuggerresume) + { + Sleep(10); + Sys_SendKeyEvents(); + + //FIXME: display a stack trace and locals instead + R2D_ImageColours((sin(Sys_DoubleTime())+1)*0.5,0, 0, 1); + R2D_FillBlock(0, 0, vid.width, vid.height); + Con_DrawConsole(vid.height/2, true); //draw console at half-height + debuggerstacky = vid.height/2; + if (debuggerstacky) + PR_StackTrace(prinst, 2); + debuggerstacky = 0; + VID_SwapBuffers(); + } + if (debuggerresume == 2) + prinst->pr_trace = false; + return debuggerresumeline; + } +#endif + +#ifdef TEXTEDITOR + if (!parms) + return QCLibEditor(prinst, filename, line, statement, nump, parms); + else + { + static char oldfuncname[64]; + if (!nump && !strncmp(oldfuncname, *parms, sizeof(oldfuncname))) + { + Con_Printf("Executing %s: %s\n", *parms, filename); + Q_strncpyz(oldfuncname, *parms, sizeof(oldfuncname)); + } + return line; + } +#else + { + int i; + char buffer[8192]; + char *r; + vfsfile_t *f; + + if (line == -1) + return line; + SV_EndRedirect(); + if (developer.value) + { + f = FS_OpenVFS(filename, "rb", FS_GAME); + } + else + f = NULL; //faster. + if (!f) + { + Q_snprintfz(buffer, sizeof(buffer), "%s/%s", pr_sourcedir.string, filename); + f = FS_OpenVFS(buffer, "rb", FS_GAME); + } + if (!f) + Con_Printf("-%s - %i\n", filename, line); + else + { + for (i = 0; i < line; i++) + { + VFS_GETS(f, buffer, sizeof(buffer)); + } + if ((r = strchr(buffer, '\r'))) + { r[0] = '\n';r[1]='\0';} + Con_Printf("-%s", buffer); + VFS_CLOSE(f); + } + } +//PF_break(NULL); + return line; +#endif +} + //tag warnings/errors for easier debugging. int PR_Printf (const char *fmt, ...) { @@ -91,6 +209,20 @@ int PR_Printf (const char *fmt, ...) *nl = 0; *file = 0; + /*when we're debugging, stack dumps should appear directly on-screen instead of being shoved on the console*/ +#ifndef SERVERONLY + if (debuggerstacky) + { + Draw_FunString(0, debuggerstacky, msg); + debuggerstacky += 8; + if (nl) + memmove(msg, nl+1, strlen(nl+1)+1); + else + break; + continue; + } +#endif + ls = strchr(msg, ':'); if (ls) { @@ -187,7 +319,7 @@ void VARGS PR_BIError(pubprogfuncs_t *progfuncs, char *format, ...) } else { - PR_StackTrace(progfuncs); + PR_StackTrace(progfuncs, false); PR_AbortStack(progfuncs); progfuncs->parms->Abort ("%s", string); } @@ -4336,7 +4468,7 @@ void QCBUILTIN PF_error (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals ED_Print (ed); */ - PR_StackTrace(prinst); + PR_StackTrace(prinst, false); Con_Printf("%s\n", s); @@ -4369,6 +4501,29 @@ void QCBUILTIN PF_localcmd (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob Cbuf_AddText (str, RESTRICT_INSECURE); } +void QCBUILTIN PF_gettime (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int timer = (prinst->callargc > 0)?G_FLOAT(OFS_PARM0):0; + switch(timer) + { + default: + case 0: //cached time at start of frame + G_FLOAT(OFS_RETURN) = realtime; + break; + case 1: //actual time + G_FLOAT(OFS_RETURN) = Sys_DoubleTime(); + break; + //case 2: //highres.. looks like time into the frame + //case 3: //uptime + //case 4: //cd track +#ifndef SERVERONLY + case 5: //sim time + G_FLOAT(OFS_RETURN) = cl.time; + break; +#endif + } +} + void QCBUILTIN PF_calltimeofday (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { date_t date; @@ -4982,6 +5137,8 @@ void PR_ProgsAdded(pubprogfuncs_t *prinst, int newprogs, const char *modulename) PO_Close(pofile); } prinst->FindPrefixGlobals (prinst, newprogs, "autocvar_", PR_FoundAutoCvarGlobal, NULL); + + QCLoadBreakpoints("", modulename); } lh_extension_t QSG_Extensions[] = { @@ -5086,6 +5243,7 @@ lh_extension_t QSG_Extensions[] = { {"DP_QC_MINMAXBOUND", 3, NULL, {"min", "max", "bound"}}, {"DP_QC_MULTIPLETEMPSTRINGS"}, {"DP_QC_RANDOMVEC", 1, NULL, {"randomvec"}}, + {"DP_QC_RENDER_SCENE"}, //clear+addentity+setviewprop+renderscene+setmodel are available to menuqc. {"DP_QC_SINCOSSQRTPOW", 4, NULL, {"sin", "cos", "sqrt", "pow"}}, {"DP_QC_STRFTIME", 1, NULL, {"strftime"}}, {"DP_QC_STRING_CASE_FUNCTIONS", 2, NULL, {"strtolower", "strtoupper"}}, @@ -5150,7 +5308,7 @@ lh_extension_t QSG_Extensions[] = { {"EXT_DIMENSION_GHOST"}, {"FRIK_FILE", 11, NULL, {"stof", "fopen","fclose","fgets","fputs","strlen","strcat","substring","stov","strzone","strunzone"}}, {"FTE_CALLTIMEOFDAY", 1, NULL, {"calltimeofday"}}, - {"FTE_CSQC_ALTCONSOLES_WIP", 4, NULL, {"con_getset", "con_print", "con_draw", "con_input"}}, + {"FTE_CSQC_ALTCONSOLES_WIP", 4, NULL, {"con_getset", "con_printf", "con_draw", "con_input"}}, {"FTE_CSQC_BASEFRAME"}, //control for all skeletal models {"FTE_CSQC_HALFLIFE_MODELS"}, //hl-specific skeletal model control {"FTE_CSQC_SERVERBROWSER", 12, NULL, { "gethostcachevalue", "gethostcachestring", "resethostcachemasks", "sethostcachemaskstring", "sethostcachemasknumber", diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index aa86fd977..3140a86dc 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -421,6 +421,7 @@ void QCBUILTIN PF_memptradd (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo void QCBUILTIN PF_soundlength (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_calltimeofday (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_gettime (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_whichpack (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index 4365300ea..11080b07a 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -1735,7 +1735,7 @@ static qbyte *Q1BSP_ClusterPVS (model_t *model, int cluster, qbyte *buffer, unsi buffersize = sizeof(decompressed); } - return Q1BSP_DecompressVis (model->leafs[cluster+1].compressed_vis, model, buffer, buffersize); + return Q1BSP_DecompressVis (model->leafs[cluster].compressed_vis, model, buffer, buffersize); } //returns the leaf number, which is used as a bit index into the pvs. diff --git a/engine/dotnet2005/ftequake.sln b/engine/dotnet2005/ftequake.sln index 27aedeaf3..ee26261c2 100644 --- a/engine/dotnet2005/ftequake.sln +++ b/engine/dotnet2005/ftequake.sln @@ -47,6 +47,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "npfte", "npfte.vcproj", "{8 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "irc", "..\..\plugins\irc\irc.vcproj", "{6ABD62A3-C5A0-43E8-BA4F-84606057774F}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "private", "..\..\plugins\private\private.vcproj", "{74542CA7-48C1-4664-9007-66F751131EA3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution D3DDebug|Win32 = D3DDebug|Win32 @@ -606,6 +608,42 @@ Global {6ABD62A3-C5A0-43E8-BA4F-84606057774F}.Release|Win32.ActiveCfg = Release|Win32 {6ABD62A3-C5A0-43E8-BA4F-84606057774F}.Release|Win32.Build.0 = Release|Win32 {6ABD62A3-C5A0-43E8-BA4F-84606057774F}.Release|x64.ActiveCfg = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.D3DDebug|Win32.ActiveCfg = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.D3DDebug|Win32.Build.0 = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.D3DDebug|x64.ActiveCfg = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.D3DRelease|Win32.ActiveCfg = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.D3DRelease|Win32.Build.0 = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.D3DRelease|x64.ActiveCfg = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.Debug Dedicated Server|x64.ActiveCfg = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.Debug|Win32.ActiveCfg = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.Debug|Win32.Build.0 = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.Debug|x64.ActiveCfg = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.GLDebug|Win32.ActiveCfg = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.GLDebug|Win32.Build.0 = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.GLDebug|x64.ActiveCfg = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.GLRelease|Win32.ActiveCfg = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.GLRelease|Win32.Build.0 = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.GLRelease|x64.ActiveCfg = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.MDebug|Win32.ActiveCfg = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.MDebug|Win32.Build.0 = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.MDebug|x64.ActiveCfg = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.MinGLDebug|Win32.ActiveCfg = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.MinGLDebug|Win32.Build.0 = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.MinGLDebug|x64.ActiveCfg = Debug|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.MinGLRelease|Win32.ActiveCfg = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.MinGLRelease|Win32.Build.0 = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.MinGLRelease|x64.ActiveCfg = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.MRelease|Win32.ActiveCfg = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.MRelease|Win32.Build.0 = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.MRelease|x64.ActiveCfg = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.Release Dedicated Server|Win32.ActiveCfg = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.Release Dedicated Server|Win32.Build.0 = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.Release Dedicated Server|x64.ActiveCfg = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.Release|Win32.ActiveCfg = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.Release|Win32.Build.0 = Release|Win32 + {74542CA7-48C1-4664-9007-66F751131EA3}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -617,6 +655,7 @@ Global {9767E236-8454-44E9-8999-CD5BDAFBE9BA} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} {72269FEE-293D-40BC-A7AE-E429F4496869} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} {6ABD62A3-C5A0-43E8-BA4F-84606057774F} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} + {74542CA7-48C1-4664-9007-66F751131EA3} = {8CED01C6-2C61-4EC5-90B6-574D9756D773} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution AMDCaProjectFile = C:\Games\Quake\wip\engine\dotnet2005\CodeAnalyst\ftequake.caw diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 4fae08182..0ab797a55 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -1272,8 +1272,38 @@ void GenerateFogTexture(texid_t *tex, float density, float zscale) R_Upload(*tex, "fog", TF_RGBA32, fogdata, NULL, FOGS, FOGT, IF_CLAMP|IF_NOMIPMAP); } +void GLBE_DestroyFBOs(void) +{ + GLBE_FBO_Destroy(&shaderstate.fbo_2dfbo); + GLBE_FBO_Destroy(&shaderstate.fbo_reflectrefrac); + GLBE_FBO_Destroy(&shaderstate.fbo_lprepass); + + if (shaderstate.tex_reflection.num) + { + R_DestroyTexture(shaderstate.tex_reflection); + shaderstate.tex_reflection = r_nulltex; + } + if (shaderstate.tex_refraction.num) + { + R_DestroyTexture(shaderstate.tex_refraction); + shaderstate.tex_refraction = r_nulltex; + } + if (shaderstate.tex_refractiondepth.num) + { + R_DestroyTexture(shaderstate.tex_refractiondepth); + shaderstate.tex_refractiondepth = r_nulltex; + } + if (shaderstate.temptexture.num) + { + R_DestroyTexture(shaderstate.temptexture); + shaderstate.temptexture = r_nulltex; + } +} + void GLBE_Shutdown(void) { + GLBE_DestroyFBOs(); + BZ_Free(shaderstate.wbatches); shaderstate.wbatches = NULL; shaderstate.maxwbatches = 0; @@ -4482,7 +4512,7 @@ void GLBE_BaseEntTextures(void) void GLBE_RenderToTextureUpdate2d(qboolean destchanged) { - unsigned int width, height; + unsigned int width = 0, height = 0; if (destchanged) { if (r_refdef.rt_destcolour) @@ -4492,6 +4522,7 @@ void GLBE_RenderToTextureUpdate2d(qboolean destchanged) } else GLBE_FBO_Push(NULL); + GL_Set2D(false); } else @@ -4889,30 +4920,7 @@ void GLBE_DrawWorld (qboolean drawworld, qbyte *vis) } if (shaderstate.oldwidth != vid.pixelwidth || shaderstate.oldheight != vid.pixelheight) { - GLBE_FBO_Destroy(&shaderstate.fbo_2dfbo); - GLBE_FBO_Destroy(&shaderstate.fbo_reflectrefrac); - GLBE_FBO_Destroy(&shaderstate.fbo_lprepass); - - if (shaderstate.tex_reflection.num) - { - R_DestroyTexture(shaderstate.tex_reflection); - shaderstate.tex_reflection = r_nulltex; - } - if (shaderstate.tex_refraction.num) - { - R_DestroyTexture(shaderstate.tex_refraction); - shaderstate.tex_refraction = r_nulltex; - } - if (shaderstate.tex_refractiondepth.num) - { - R_DestroyTexture(shaderstate.tex_refractiondepth); - shaderstate.tex_refractiondepth = r_nulltex; - } - if (shaderstate.temptexture.num) - { - R_DestroyTexture(shaderstate.temptexture); - shaderstate.temptexture = r_nulltex; - } + GLBE_DestroyFBOs(); //will be recreated on demand shaderstate.oldwidth = vid.pixelwidth; shaderstate.oldheight = vid.pixelheight; diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 4456224a1..a687db2bb 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -546,6 +546,7 @@ void GLDraw_DeInit (void) GL_GAliasFlushSkinCache(); draw_disc = NULL; + GL_ShutdownPostProcessing(); if (uploadmemorybuffer) BZ_Free(uploadmemorybuffer); //free the mem diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index a08242617..bc8c50b06 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -126,6 +126,11 @@ void GL_InitSceneProcessingShaders_WaterWarp (void) } } +void GL_ShutdownPostProcessing(void) +{ + GLBE_FBO_Destroy(&fbo_gameview); +} + void GL_InitSceneProcessingShaders (void) { if (gl_config.arb_shader_objects) diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 5b99250ce..7801c973d 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -375,6 +375,7 @@ qboolean R_ShouldDraw(entity_t *e); #ifdef GLQUAKE void R_RotateForEntity (float *modelmatrix, float *modelviewmatrix, const entity_t *e, const model_t *mod); +void GL_ShutdownPostProcessing(void); void GL_InitSceneProcessingShaders (void); void GL_SetupSceneProcessingTextures (void); #endif diff --git a/engine/gl/shader.h b/engine/gl/shader.h index d87d13743..7f5ba21db 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -321,23 +321,23 @@ enum{ enum shaderattribs_e { - VATTR_VERTEX1, - VATTR_VERTEX2, - VATTR_COLOUR, - VATTR_TEXCOORD, - VATTR_LMCOORD, - VATTR_NORMALS, - VATTR_SNORMALS, - VATTR_TNORMALS, - VATTR_BONENUMS, /*skeletal only*/ - VATTR_BONEWEIGHTS, /*skeletal only*/ + VATTR_VERTEX1=0, //NOTE: read the comment about VATTR_LEG_VERTEX + VATTR_VERTEX2=1, + VATTR_COLOUR=2, + VATTR_TEXCOORD=3, + VATTR_LMCOORD=4, + VATTR_NORMALS=5, + VATTR_SNORMALS=6, + VATTR_TNORMALS=7, + VATTR_BONENUMS=8, /*skeletal only*/ + VATTR_BONEWEIGHTS=9, /*skeletal only*/ #if MAXRLIGHTMAPS > 1 - VATTR_LMCOORD2, - VATTR_LMCOORD3, - VATTR_LMCOORD4, - VATTR_COLOUR2, - VATTR_COLOUR3, - VATTR_COLOUR4, + VATTR_LMCOORD2=10, + VATTR_LMCOORD3=11, + VATTR_LMCOORD4=12, + VATTR_COLOUR2=13, + VATTR_COLOUR3=14, + VATTR_COLOUR4=15, #endif diff --git a/engine/qclib/comprout.c b/engine/qclib/comprout.c index 5f9b169a7..220811aac 100644 --- a/engine/qclib/comprout.c +++ b/engine/qclib/comprout.c @@ -74,7 +74,7 @@ pbool PreCompile(void) return !!qcchunk; } -void QCC_main (int argc, char **argv); +pbool QCC_main (int argc, char **argv); void QCC_ContinueCompile(void); void QCC_FinishCompile(void); @@ -99,9 +99,8 @@ pbool CompileParams(progfuncs_t *progfuncs, int doall, int nump, char **parms) return false; } - if (!PreCompile()) + if (!QCC_main(nump, parms)) return false; - QCC_main(nump, parms); while(qcc_compileactive) QCC_ContinueCompile(); @@ -124,9 +123,8 @@ int PDECL Comp_Begin(pubprogfuncs_t *progfuncs, int nump, char **parms) return false; } - if (!PreCompile()) + if (!QCC_main(nump, parms)) return false; - QCC_main(nump, parms); return true; } diff --git a/engine/qclib/execloop.h b/engine/qclib/execloop.h index ba19801b6..0f6eb6b69 100644 --- a/engine/qclib/execloop.h +++ b/engine/qclib/execloop.h @@ -681,7 +681,7 @@ reeval: PR_SwitchProgsParms(progfuncs, callerprogs); //break/skip the instruction. - PR_StackTrace(&progfuncs->funcs); + PR_StackTrace(&progfuncs->funcs, 0); printf(msg, PR_StringToNative(&progfuncs->funcs, pr_xfunction->s_name)); glob = pr_globals; diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index 6f60ee2a2..e8def347d 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -218,7 +218,7 @@ static void *PDECL PR_memalloc (pubprogfuncs_t *ppf, unsigned int size) if (b < 0 || b+sizeof(qcmemfreeblock_t) >= prinst.addressableused) { printf("PF_memalloc: memory corruption\n"); - PR_StackTrace(&progfuncs->funcs); + PR_StackTrace(&progfuncs->funcs, false); return NULL; } p = (qcmemfreeblock_t*)(progfuncs->funcs.stringtable + b); @@ -230,7 +230,7 @@ static void *PDECL PR_memalloc (pubprogfuncs_t *ppf, unsigned int size) p->prev >= b) { printf("PF_memalloc: memory corruption\n"); - PR_StackTrace(&progfuncs->funcs); + PR_StackTrace(&progfuncs->funcs, false); return NULL; } @@ -274,7 +274,7 @@ static void *PDECL PR_memalloc (pubprogfuncs_t *ppf, unsigned int size) if (!ub) { printf("PF_memalloc: memory exausted\n"); - PR_StackTrace(&progfuncs->funcs); + PR_StackTrace(&progfuncs->funcs, false); return NULL; } } @@ -309,7 +309,7 @@ static void PDECL PR_memfree (pubprogfuncs_t *ppf, void *memptr) } else printf("PF_memfree: pointer invalid - out of range (%x >= %x)\n", ptr, (unsigned int)prinst.addressableused); - PR_StackTrace(&progfuncs->funcs); + PR_StackTrace(&progfuncs->funcs, false); return; } @@ -319,7 +319,7 @@ static void PDECL PR_memfree (pubprogfuncs_t *ppf, void *memptr) if (ub->marker != MARKER || ub->size <= sizeof(*ub) || ptr + ub->size > (unsigned int)prinst.addressableused) { printf("PR_memfree: pointer lacks marker - double-freed?\n"); - PR_StackTrace(&progfuncs->funcs); + PR_StackTrace(&progfuncs->funcs, false); return; } ub->marker = 0; @@ -330,7 +330,7 @@ static void PDECL PR_memfree (pubprogfuncs_t *ppf, void *memptr) if (na < 0 || na >= prinst.addressableused) { printf("PF_memfree: memory corruption\n"); - PR_StackTrace(&progfuncs->funcs); + PR_StackTrace(&progfuncs->funcs, false); return; } if (!na || na >= ptr) @@ -339,7 +339,7 @@ static void PDECL PR_memfree (pubprogfuncs_t *ppf, void *memptr) if (pa && pa+np->size>ptr) { printf("PF_memfree: double free\n"); - PR_StackTrace(&progfuncs->funcs); + PR_StackTrace(&progfuncs->funcs, false); return; } @@ -797,7 +797,7 @@ struct edict_s *PDECL ProgsToEdict (pubprogfuncs_t *ppf, int progs) printf("Bad entity index %i\n", progs); if (pr_depth) { - PR_StackTrace (ppf); + PR_StackTrace (ppf, false); // progfuncs->funcs.pr_trace += 1; } progs = 0; @@ -904,7 +904,7 @@ char *ASMCALL PR_StringToNative (pubprogfuncs_t *ppf, string_t str) if (i >= prinst.numallocedstrings) { printf("invalid string %x\n", str); - PR_StackTrace(&progfuncs->funcs); + PR_StackTrace(&progfuncs->funcs, false); progfuncs->funcs.pr_trace = 1; return ""; } @@ -913,7 +913,7 @@ char *ASMCALL PR_StringToNative (pubprogfuncs_t *ppf, string_t str) else { printf("invalid string %x\n", str); - PR_StackTrace(&progfuncs->funcs); + PR_StackTrace(&progfuncs->funcs, false); progfuncs->funcs.pr_trace = 1; return ""; //urm, was freed... } @@ -924,7 +924,7 @@ char *ASMCALL PR_StringToNative (pubprogfuncs_t *ppf, string_t str) if (i >= prinst.numtempstrings) { printf("invalid temp string %x\n", str); - PR_StackTrace(&progfuncs->funcs); + PR_StackTrace(&progfuncs->funcs, false); progfuncs->funcs.pr_trace = 1; return ""; } @@ -934,7 +934,7 @@ char *ASMCALL PR_StringToNative (pubprogfuncs_t *ppf, string_t str) if ((unsigned int)str >= (unsigned int)prinst.addressableused) { printf("invalid string offset %x\n", str); - PR_StackTrace(&progfuncs->funcs); + PR_StackTrace(&progfuncs->funcs, false); progfuncs->funcs.pr_trace = 1; return ""; } diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 9251c41e5..832108f04 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -10,8 +10,6 @@ struct edict_s; #define NOENDIAN #endif - -fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs); pbool ED_ParseEpair (progfuncs_t *progfuncs, int qcptr, unsigned int fldofs, int fldtype, char *s); /* @@ -240,6 +238,25 @@ fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs) } return NULL; } +fdef_t *ED_ClassFieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs, const char *classname) +{ + int classnamelen = strlen(classname); + unsigned int j; + char *mname; + for (j = 0; j < prinst.numfields; j++) + { + if (prinst.field[j].ofs == ofs) + { + mname = prinst.field[j].name; + if (!strncmp(mname, classname, classnamelen) && mname[classnamelen] == ':') + { + //okay, we have a match... + return &prinst.field[j]; + } + } + } + return ED_FieldAtOfs(progfuncs, ofs); +} fdef_t *PDECL ED_FieldInfo (pubprogfuncs_t *ppf, unsigned int *count) { progfuncs_t *progfuncs = (progfuncs_t*)ppf; diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index c5c9bfcef..fb732a93a 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -238,18 +238,80 @@ char *QC_ucase(char *str) return s; } -//#define STACKTRACE -void PDECL PR_StackTrace (pubprogfuncs_t *ppf) +static void PDECL PR_PrintRelevantLocals(progfuncs_t *progfuncs) +{ + //scan for op_address/op_load instructions within the function + int st, st2; + int op; + dstatement16_t *st16 = current_progstate->statements; + int line; + if (!current_progstate->linenums || current_progstate->structtype != PST_DEFAULT) + return; + + line = current_progstate->linenums[pr_xstatement]; + for (st = pr_xfunction->first_statement; st16[st].op != OP_DONE; st++) + { + if (current_progstate->linenums[st] < line - 2 || current_progstate->linenums[st] > line + 2) + continue; //don't go crazy with this. + op = st16[st].op & ~0x8000; + if (op == OP_ADDRESS || (op >= OP_LOAD_F && op <= OP_LOAD_FNC) || op == OP_LOAD_I || op == OP_LOAD_P) + { + ddef16_t *ent = ED_GlobalAtOfs16(progfuncs, st16[st].a); + ddef16_t *fld = ED_GlobalAtOfs16(progfuncs, st16[st].b); + pbool skip = false; + edictrun_t *ed; + eval_t *ptr; + fdef_t *fdef; + fdef_t *cnfd; + char *classname; + if (!ent || !fld) + continue; + //all this extra code to avoid printing dupes... + for (st2 = st-1; st2 >= pr_xfunction->first_statement; st2--) + { + if (current_progstate->linenums[st2] < line - 2 || current_progstate->linenums[st2] > line + 2) + continue; + op = st16[st2].op & ~0x8000; + if (op == OP_ADDRESS || (op >= OP_LOAD_F && op <= OP_LOAD_FNC) || op == OP_LOAD_I || op == OP_LOAD_P) + if (st16[st].a == st16[st2].a && st16[st].b == st16[st2].b) + { + skip = true; + break; + } + } + if (skip) + continue; + ed = PROG_TO_EDICT(progfuncs, ((eval_t *)&pr_globals[st16[st].a])->edict); + ptr = (eval_t *)(((int *)edvars(ed)) + ((eval_t *)&pr_globals[st16[st].b])->_int + progfuncs->funcs.fieldadjust); + + cnfd = ED_FindField(progfuncs, "classname"); + if (cnfd) + { + string_t *v = (string_t *)((char *)edvars(ed) + cnfd->ofs*4); + classname = PR_StringToNative(&progfuncs->funcs, *v); + } + else + classname = ""; + if (*classname) + fdef = ED_ClassFieldAtOfs(progfuncs, ((eval_t *)&pr_globals[st16[st].b])->_int, classname); + else + fdef = ED_FieldAtOfs(progfuncs, ((eval_t *)&pr_globals[st16[st].b])->_int); + if (fdef) + printf(" %s.%s: %s\n", ent->s_name+progfuncs->funcs.stringtable, fld->s_name+progfuncs->funcs.stringtable, PR_ValueString(progfuncs, fdef->type, ptr, false)); + else + printf(" %s.%s: BAD FIELD DEF - %#x\n", ent->s_name+progfuncs->funcs.stringtable, fld->s_name+progfuncs->funcs.stringtable, ptr->_int); + } + } +} + +void PDECL PR_StackTrace (pubprogfuncs_t *ppf, int showlocals) { progfuncs_t *progfuncs = (progfuncs_t *)ppf; const dfunction_t *f; int i; int progs; - -#ifdef STACKTRACE int arg; int *globalbase; -#endif progs = -1; if (pr_depth == 0) @@ -258,9 +320,8 @@ void PDECL PR_StackTrace (pubprogfuncs_t *ppf) return; } -#ifdef STACKTRACE - globalbase = (int *)pr_globals + pr_xfunction->parm_start - pr_xfunction->locals; -#endif + //point this to the function's locals + globalbase = (int *)pr_globals + pr_xfunction->parm_start + pr_xfunction->locals; pr_stack[pr_depth].f = pr_xfunction; pr_stack[pr_depth].s = pr_xstatement; @@ -274,6 +335,8 @@ void PDECL PR_StackTrace (pubprogfuncs_t *ppf) } else { + globalbase -= f->locals; + if (pr_stack[i].progsnum != progs) { progs = pr_stack[i].progsnum; @@ -290,8 +353,10 @@ void PDECL PR_StackTrace (pubprogfuncs_t *ppf) printf ("%12s : %s\n", f->s_file+progfuncs->funcs.stringtable, f->s_name+progfuncs->funcs.stringtable); } -#ifdef STACKTRACE - if (i == pr_depth) + //locals:0 = no locals + //locals:1 = top only + //locals:2 = ALL locals. + if ((i == pr_depth && showlocals == 1) || showlocals >= 2) for (arg = 0; arg < f->locals; arg++) { ddef16_t *local; @@ -302,17 +367,18 @@ void PDECL PR_StackTrace (pubprogfuncs_t *ppf) } else { - printf(" %s: %s\n", local->s_name+progfuncs->funcs.stringtable, PR_ValueString(progfuncs, local->type, (eval_t*)(globalbase - f->locals+arg), false)); + printf(" %s: %s\n", local->s_name+progfuncs->funcs.stringtable, PR_ValueString(progfuncs, local->type, (eval_t*)(globalbase+arg), false)); if (local->type == ev_vector) arg+=2; } } + if (i == pr_depth) + { //scan for op_address/op_load instructions within the function + PR_PrintRelevantLocals(progfuncs); + } if (i == pr_depth) globalbase = localstack + localstack_used; - else - globalbase -= f->locals; -#endif } } } @@ -379,7 +445,7 @@ void VARGS PR_RunError (pubprogfuncs_t *progfuncs, char *error, ...) // } // PR_PrintStatement (pr_statements + pr_xstatement); - PR_StackTrace (progfuncs); + PR_StackTrace (progfuncs, true); progfuncs->parms->Printf ("\n"); //editbadfile(pr_strings + pr_xfunction->s_file, -1); @@ -400,7 +466,7 @@ pbool PR_RunWarning (pubprogfuncs_t *progfuncs, char *error, ...) va_end (argptr); progfuncs->parms->Printf ("%s, %s\n", string, ((progfuncs->pr_trace)?"ignoring":"enabling trace")); - PR_StackTrace (progfuncs); + PR_StackTrace (progfuncs, false); if (progfuncs->pr_trace++ == 0) return true; @@ -434,7 +500,7 @@ int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, dfunction_t *f, int progsn if (pr_depth == MAX_STACK_DEPTH) { pr_depth--; - PR_StackTrace (&progfuncs->funcs); + PR_StackTrace (&progfuncs->funcs, false); printf ("stack overflow on call to %s (depth %i)\n", progfuncs->funcs.stringtable+f->s_name, pr_depth); @@ -1105,6 +1171,7 @@ static char *lastfile = 0; int pn = pr_typecurrent; int i; const dfunction_t *f = pr_xfunction; + pr_xstatement = statement; if (!externs->useeditor) { @@ -1163,7 +1230,7 @@ static char *lastfile = 0; { \ pr_xstatement = st-pr_statements; \ PR_RunError (&progfuncs->funcs, "runaway loop error\n");\ - PR_StackTrace(&progfuncs->funcs); \ + PR_StackTrace(&progfuncs->funcs,false); \ printf ("runaway loop error\n"); \ while(pr_depth > prinst.exitdepth) \ PR_LeaveFunction(progfuncs); \ @@ -1197,7 +1264,7 @@ static int PR_ExecuteCode16 (progfuncs_t *fte_restrict progfuncs, int s, int *ft #ifdef FTE_TARGET_WEB //this can generate huge functions, so disable it on systems that can't realiably cope with such things (IE initiates an unwanted denial-of-service attack when pointed our javascript, and firefox prints a warning too) pr_xstatement = st-pr_statements; - PR_RunError (&progfuncs->funcs, "runaway loop error\n"); + PR_RunError (&progfuncs->funcs, "This platform does not support QC debugging.\n"); PR_StackTrace(&progfuncs->funcs); return -1; #else @@ -1244,8 +1311,8 @@ static int PR_ExecuteCode32 (progfuncs_t *fte_restrict progfuncs, int s, int *ft #ifdef FTE_TARGET_WEB //this can generate huge functions, so disable it on systems that can't realiably cope with such things (IE initiates an unwanted denial-of-service attack when pointed our javascript, and firefox prints a warning too) pr_xstatement = st-pr_statements; - PR_RunError (&progfuncs->funcs, "runaway loop error\n"); - PR_StackTrace(&progfuncs->funcs); + PR_RunError (&progfuncs->funcs, "This platform does not support QC debugging.\n"); + PR_StackTrace(&progfuncs->funcs, false); return -1; #else #define DEBUGABLE diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index 6dbc36707..2090bb46c 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -281,7 +281,7 @@ char *PDECL PR_SaveEnts(pubprogfuncs_t *progfuncs, char *mem, int *size, int max int PDECL PR_LoadEnts(pubprogfuncs_t *progfuncs, const char *file, float killonspawnflags); char *PDECL PR_SaveEnt (pubprogfuncs_t *progfuncs, char *buf, int *size, int maxsize, struct edict_s *ed); struct edict_s *PDECL PR_RestoreEnt (pubprogfuncs_t *progfuncs, const char *buf, int *size, struct edict_s *ed); -void PDECL PR_StackTrace (pubprogfuncs_t *progfuncs); +void PDECL PR_StackTrace (pubprogfuncs_t *progfuncs, int showlocals); extern int noextensions; @@ -475,6 +475,7 @@ ddef32_t *ED_FindTypeGlobalFromProgs32 (progfuncs_t *progfuncs, const char *name ddef16_t *ED_FindGlobalFromProgs16 (progfuncs_t *progfuncs, const char *name, progsnum_t prnum); ddef32_t *ED_FindGlobalFromProgs32 (progfuncs_t *progfuncs, const char *name, progsnum_t prnum); fdef_t *ED_FindField (progfuncs_t *progfuncs, const char *name); +fdef_t *ED_ClassFieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs, const char *classname); fdef_t *ED_FieldAtOfs (progfuncs_t *progfuncs, unsigned int ofs); dfunction_t *ED_FindFunction (progfuncs_t *progfuncs, const char *name, progsnum_t *pnum, progsnum_t fromprogs); func_t PDECL PR_FindFunc(pubprogfuncs_t *progfncs, const char *funcname, progsnum_t pnum); diff --git a/engine/qclib/progslib.h b/engine/qclib/progslib.h index 93442b8bd..66172d1f0 100644 --- a/engine/qclib/progslib.h +++ b/engine/qclib/progslib.h @@ -117,7 +117,7 @@ struct pubprogfuncs_s int pr_trace; //start calling the editor for each line executed - void (PDECL *StackTrace) (pubprogfuncs_t *prinst); + void (PDECL *StackTrace) (pubprogfuncs_t *prinst, int showlocals); int (PDECL *ToggleBreak) (pubprogfuncs_t *prinst, char *filename, int linenum, int mode); @@ -265,7 +265,7 @@ typedef union eval_s #define PR_StartCompile(pf,argc,argv) (*pf->StartCompile) (pf,argc,argv) #define PR_ContinueCompile(pf) (*pf->ContinueCompile) (pf) -#define PR_StackTrace(pf) (*pf->StackTrace) (pf) +#define PR_StackTrace(pf,locals) (*pf->StackTrace) (pf,locals) #define PR_AbortStack(pf) (*pf->AbortStack) (pf) #define PR_RunError(pf,str) (*pf->RunError) (pf,str) diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index c6c54b04a..41dfd08c8 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -553,6 +553,7 @@ extern pbool opt_stripfunctions; extern pbool opt_locals_overlapping; extern pbool opt_logicops; extern pbool opt_vectorcalls; +extern pbool opt_classfields; extern int optres_shortenifnots; extern int optres_overlaptemps; @@ -836,6 +837,7 @@ void QCC_PR_NewLine (pbool incomment); #define GDF_STATIC 2 #define GDF_CONST 4 #define GDF_STRIP 8 //always stripped, regardless of optimisations. used for class member fields +#define GDF_SILENT 16 //used by the gui, to suppress ALL warnings. QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool allocate, int arraysize, unsigned int flags); char *QCC_PR_CheckCompConstTooltip(char *word, char *outstart, char *outend); diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index a33acb584..d7384de5d 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -637,7 +637,7 @@ pbool OpAssignsToB(unsigned int op) return true; if(op >= OP_MULSTORE_F && op <= OP_SUBSTOREP_V) return true; - if(op >= OP_STORE_F && op <= OP_STOREP_FNC) + if((op >= OP_STORE_F && op <= OP_STOREP_FNC) || op == OP_STOREP_P || op == OP_STORE_P) return true; return false; } @@ -4983,14 +4983,13 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype) // QCC_PR_EmitFieldsForMembers(basetype, basictypefield); - - + pr_source_line = 0; pr_scope = scope; df = &functions[numfunctions]; numfunctions++; - df->s_file = scope->s_file; + df->s_file = 0; df->s_name = QCC_CopyString(scope->name); df->first_statement = numstatements; df->parm_size[0] = 1; @@ -6525,8 +6524,8 @@ QCC_def_t *QCC_StoreToRef(QCC_ref_t *dest, QCC_def_t *source, pbool readable, pb break; t = t->parentclass; } - if (!t) - { + if (!t && !(source->type->type == ev_pointer && dest->cast->type == ev_pointer && (source->type->aux_type->type == ev_void || source->type->aux_type->type == ev_variant))) + { //extra check to allow void*->any* char typea[256]; char typeb[256]; TypeName(source->type, typea, sizeof(typea)); @@ -9597,18 +9596,18 @@ void QCC_PR_EmitArrayGetFunction(QCC_def_t *scope, QCC_def_t *thearray, char *ar QCC_def_t *fasttrackpossible; int numslots; - if (flag_fasttrackarrays) + if (thearray->type->type == ev_vector) + numslots = thearray->arraysize; + else + numslots = thearray->arraysize*thearray->type->size; + + if (flag_fasttrackarrays && numslots > 6) fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false); else fasttrackpossible = NULL; s_file = scope->s_file; - if (thearray->type->type == ev_vector) - numslots = thearray->arraysize; - else - numslots = thearray->arraysize*thearray->type->size; - if (numslots >= 15 && thearray->type->type != ev_vector) vectortrick = QCC_PR_EmitArrayGetVector(thearray); else @@ -9774,7 +9773,12 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, QCC_def_t *thearray, char *ar QCC_def_t *fasttrackpossible; int numslots; - if (flag_fasttrackarrays) + if (thearray->type->type == ev_vector) + numslots = thearray->arraysize; + else + numslots = thearray->arraysize*thearray->type->size; + + if (flag_fasttrackarrays && numslots > 6) fasttrackpossible = QCC_PR_GetDef(type_float, "__ext__fasttrackarrays", NULL, true, 0, false); else fasttrackpossible = NULL; @@ -9782,11 +9786,6 @@ void QCC_PR_EmitArraySetFunction(QCC_def_t *scope, QCC_def_t *thearray, char *ar s_file = scope->s_file; pr_scope = scope; - if (thearray->type->type == ev_vector) - numslots = thearray->arraysize; - else - numslots = thearray->arraysize*thearray->type->size; - if (numfunctions >= MAX_FUNCTIONS) QCC_Error(ERR_INTERNAL, "Too many function defs"); @@ -10164,7 +10163,7 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool } } - if (foundstatic && !allocate) + if (foundstatic && !allocate && !(flags & GDF_SILENT)) { QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s defined static", name); QCC_PR_ParsePrintDef(WARN_DUPLICATEDEFINITION, foundstatic); diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index 3e29b4206..9ca797b36 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -4571,7 +4571,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) //actually, that seems pointless. sprintf(membername, "%s::"MEMBERFIELDNAME, classname, parmname); // printf("define %s -> %s\n", membername, d->name); - d = QCC_PR_DummyDef(fieldtype, membername, pr_scope, 0, d->ofs, true, (isnull?0:GDF_CONST)|GDF_STRIP); + d = QCC_PR_DummyDef(fieldtype, membername, pr_scope, 0, d->ofs, true, (isnull?0:GDF_CONST)|(opt_classfields?GDF_STRIP:0)); d->references++; //always referenced, so you can inherit safely. } diff --git a/engine/qclib/qccgui.c b/engine/qclib/qccgui.c index d7647b7f9..b660e9e92 100644 --- a/engine/qclib/qccgui.c +++ b/engine/qclib/qccgui.c @@ -9,9 +9,11 @@ #include "qcc.h" #include "gui.h" -//#define EMBEDDEBUG +#define EMBEDDEBUG void AddSourceFile(char *format, ...); +void GUI_ParseCommandLine(char *args); +void GUI_RevealOptions(void); #ifndef TVM_SETBKCOLOR #define TVM_SETBKCOLOR (TV_FIRST + 29) @@ -38,6 +40,187 @@ void AddSourceFile(char *format, ...); #define TTM_TRACKPOSITION (WM_USER + 18) #endif + +//scintilla stuff +#define SCI_GETLENGTH 2006 +#define SCI_GETCURRENTPOS 2008 +#define SCI_SETSAVEPOINT 2014 +#define SCI_GETCURLINE 2027 +#define SCI_SETCODEPAGE 2037 +#define SCI_MARKERADD 2043 +#define SCI_MARKERDELETE 2044 +#define SCI_MARKERDELETEALL 2045 +#define SCI_MARKERGET 2046 +#define SCI_MARKERNEXT 2047 +#define SCI_STYLECLEARALL 2050 +#define SCI_STYLESETFORE 2051 +#define SCI_AUTOCSHOW 2100 +#define SCI_AUTOCCANCEL 2101 +#define SCI_AUTOCACTIVE 2102 +#define SCI_AUTOCSETFILLUPS 2112 +#define SCI_GETLINE 2153 +#define SCI_LINEFROMPOSITION 2166 +#define SCI_POSITIONFROMLINE 2167 +#define SCI_SETTEXT 2181 +#define SCI_GETTEXT 2182 +#define SCI_CALLTIPSHOW 2200 +#define SCI_CALLTIPCANCEL 2201 +#define SCI_SETMARGINSENSITIVEN 2246 +#define SCI_SETMOUSEDWELLTIME 2264 +#define SCI_LINELENGTH 2350 +#define SCI_AUTOCSETORDER 2660 +#define SCI_SETLEXER 4001 +#define SCI_SETPROPERTY 4004 +#define SCI_SETKEYWORDS 4005 + +#define SC_ORDER_PERFORMSORT 1 + +#define SC_CP_UTF8 65001 +#define SCLEX_CPP 3 + +#define SCE_C_DEFAULT 0 +#define SCE_C_COMMENT 1 +#define SCE_C_COMMENTLINE 2 +#define SCE_C_COMMENTDOC 3 +#define SCE_C_NUMBER 4 +#define SCE_C_WORD 5 +#define SCE_C_STRING 6 +#define SCE_C_CHARACTER 7 +#define SCE_C_UUID 8 +#define SCE_C_PREPROCESSOR 9 +#define SCE_C_OPERATOR 10 +#define SCE_C_IDENTIFIER 11 +#define SCE_C_STRINGEOL 12 +#define SCE_C_VERBATIM 13 +#define SCE_C_REGEX 14 +#define SCE_C_COMMENTLINEDOC 15 +#define SCE_C_WORD2 16 +#define SCE_C_COMMENTDOCKEYWORD 17 +#define SCE_C_COMMENTDOCKEYWORDERROR 18 +#define SCE_C_GLOBALCLASS 19 +#define SCE_C_STRINGRAW 20 +#define SCE_C_TRIPLEVERBATIM 21 +#define SCE_C_HASHQUOTEDSTRING 22 +#define SCE_C_PREPROCESSORCOMMENT 23 +#define SCE_C_PREPROCESSORCOMMENTDOC 24 +#define SCE_C_USERLITERAL 25 +#define SCE_C_TASKMARKER 26 +#define SCE_C_ESCAPESEQUENCE 27 + +#define SCN_CHARADDED 2001 +#define SCN_SAVEPOINTREACHED 2002 +#define SCN_SAVEPOINTLEFT 2003 +#define SCN_MARGINCLICK 2010 +#define SCN_DWELLSTART 2016 +#define SCN_DWELLEND 2017 +#define SCN_FOCUSOUT 2029 + +struct SCNotification { + NMHDR nmhdr; + int position; + int ch; + int modifiers; + int modificationType; + const char *text; + int length; + int linesAdded; + int message; + DWORD_PTR wParam; + LONG_PTR lParam; + int line; + int foldLevelNow; + int foldLevelPrev; + int margin; + int listType; + int x; + int y; + int token; + int annotationLinesAdded; + int updated; +}; + + +//these all run on the main thread +typedef struct editor_s { + char filename[MAX_PATH]; //abs + HWND window; + HWND editpane; + HWND tooltip; + char tooltiptext[1024]; + int curline; + pbool modified; + pbool scintilla; + time_t filemodifiedtime; + struct editor_s *next; +} editor_t; +editor_t *editors; + +//the engine thread simply sits waiting for responses from the engine +typedef struct +{ + int pipeclosed; + DWORD tid; + HWND window; + HANDLE thread; + HANDLE pipefromengine; + HANDLE pipetoengine; +} enginewindow_t; + +void EngineCommand(enginewindow_t *ctx, char *message, ...) +{ + //qcresume - resume running + //qcinto - singlestep. execute-with-debugging child functions + //qcover - singlestep. execute-without-debugging child functions + //qcout - singlestep. leave current function and enter parent. + //qcbreak "$loc" - set breakpoint + //qcwatch "$var" - set watchpoint + //qcstack - force-report stack trace + va_list va; + char finalmessage[1024]; + va_start (va, message); + vsnprintf (finalmessage, sizeof(finalmessage)-1, message, va); + va_end (va); + if (ctx->pipetoengine) + { + DWORD written = 0; + WriteFile(ctx->pipetoengine, finalmessage, strlen(finalmessage), &written, NULL); + } +} + + +static pbool QCC_RegGetStringValue(HKEY base, char *keyname, char *valuename, void *data, int datalen) +{ + pbool result = false; + HKEY subkey; + DWORD type = REG_NONE; + if (RegOpenKeyEx(base, keyname, 0, KEY_READ, &subkey) == ERROR_SUCCESS) + { + DWORD dwlen = datalen-1; + result = ERROR_SUCCESS == RegQueryValueEx(subkey, valuename, NULL, &type, data, &dwlen); + datalen = dwlen; + RegCloseKey (subkey); + } + + if (type == REG_SZ || type == REG_EXPAND_SZ) + ((char*)data)[datalen] = 0; + else + ((char*)data)[0] = 0; + return result; +} +static pbool QCC_RegSetValue(HKEY base, char *keyname, char *valuename, int type, void *data, int datalen) +{ + pbool result = false; + HKEY subkey; + + if (RegCreateKeyEx(base, keyname, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &subkey, NULL) == ERROR_SUCCESS) + { + if (ERROR_SUCCESS == RegSetValueEx(subkey, valuename, 0, type, data, datalen)) + result = true; + RegCloseKey (subkey); + } + return result; +} + /* ============== LoadFile @@ -79,9 +262,9 @@ int PDECL QCC_FileSize (const char *fname) #include "../libs/zlib.h" #endif -pbool PDECL QCC_WriteFileW (const char *name, wchar_t *data, int chars) +pbool PDECL QCC_WriteFileW (const char *name, wchar_t *data, int maxchars) { - char *u8start = malloc(3+chars*4+1); + char *u8start = malloc(3+maxchars*4+1); char *u8 = u8start; int offset; pbool result = false; @@ -287,15 +470,16 @@ void GUIPrint(HWND wnd, char *msg); char finddef[256]; char greptext[256]; -char enginebinary[MAX_PATH] = "fteglqw.exe"; -char enginebasedir[MAX_PATH] = "../.."; -char enginecommandline[8192] = "-game test -window +map start"; +char enginebinary[MAX_PATH]; +char enginebasedir[MAX_PATH]; +char enginecommandline[8192]; void RunCompiler(char *args); void RunEngine(void); HINSTANCE ghInstance; HMODULE richedit; +HMODULE scintilla; pbool resetprogssrc; //progs.src was changed, reload project info. @@ -322,7 +506,7 @@ struct{ {"Compile"}, {"Progs.src"}, #ifdef EMBEDDEBUG - {"Run"}, + {"Debug"}, #endif {"Options"}, {"Quit"} @@ -363,31 +547,96 @@ LRESULT CALLBACK MySubclassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l } if (wParam == VK_F5) { - RunEngine(); + if (gamewindow) + { + enginewindow_t *e = (enginewindow_t*)(LONG_PTR)GetWindowLongPtr(gamewindow, GWLP_USERDATA); + EngineCommand(e, "qcresume\n"); + } + else + RunEngine(); + return 0; + } + if (wParam == VK_F9) + { + editor_t *editor; + int mode; + for (editor = editors; editor; editor = editor->next) + { + if (editor->editpane == hWnd) + break; + } + if (editor->scintilla) + { + mode = !(SendMessage(editor->editpane, SCI_MARKERGET, editor->curline, 0) & 1); + SendMessage(editor->editpane, mode?SCI_MARKERADD:SCI_MARKERDELETE, editor->curline, 0); + } + else + mode = 2; + + if (gamewindow) + { + enginewindow_t *e = (enginewindow_t*)(LONG_PTR)GetWindowLongPtr(gamewindow, GWLP_USERDATA); + EngineCommand(e, "qcbreakpoint %i \"%s\" %i\n", mode, editor->filename, editor->curline+1); + } + return 0; + } + if (wParam == VK_F11) + { + if (gamewindow) + { + enginewindow_t *e = (enginewindow_t*)(LONG_PTR)GetWindowLongPtr(gamewindow, GWLP_USERDATA); + EngineCommand(e, "qcstep\n"); + } return 0; } } return pDefSubclassProc(hWnd, uMsg, wParam, lParam); } -HWND CreateAnEditControl(HWND parent) +HWND CreateAnEditControl(HWND parent, pbool *scintillaokay) { - HWND newc; + HWND newc = NULL; + + if (!scintilla && scintillaokay) + scintilla = LoadLibrary("SciLexer.dll"); if (!richedit) richedit = LoadLibrary("RICHED32.DLL"); - newc=CreateWindowExW(WS_EX_CLIENTEDGE, - richedit?RICHEDIT_CLASSW:L"EDIT", - L"", - WS_CHILD /*| ES_READONLY*/ | WS_VISIBLE | - WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN | - ES_MULTILINE | ES_AUTOVSCROLL, - 0, 0, 0, 0, - parent, - NULL, - ghInstance, - NULL); + if (!newc && scintilla && scintillaokay) + { + newc=CreateWindowEx(WS_EX_CLIENTEDGE, + "Scintilla", + "", + WS_CHILD /*| ES_READONLY*/ | WS_VISIBLE | + WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN | + ES_MULTILINE | ES_AUTOVSCROLL, + 0, 0, 0, 0, + parent, + NULL, + ghInstance, + NULL); + } + if (newc) + *scintillaokay = true; + else if (scintillaokay) + { + *scintillaokay = false; + scintillaokay = NULL; + } + + if (!newc) + newc=CreateWindowExW(WS_EX_CLIENTEDGE, + richedit?RICHEDIT_CLASSW:L"EDIT", + L"", + WS_CHILD /*| ES_READONLY*/ | WS_VISIBLE | + WS_HSCROLL | WS_VSCROLL | ES_LEFT | ES_WANTRETURN | + ES_MULTILINE | ES_AUTOVSCROLL, + 0, 0, 0, 0, + parent, + NULL, + ghInstance, + NULL); if (!newc) newc=CreateWindowEx(WS_EX_CLIENTEDGE, @@ -418,9 +667,63 @@ HWND CreateAnEditControl(HWND parent) ghInstance, NULL); } + if (!newc) + return NULL; - //go to lucidia console, 10pt + if (scintillaokay) { + SendMessage(newc, SCI_SETCODEPAGE, SC_CP_UTF8, 0); + SendMessage(newc, SCI_SETLEXER, SCLEX_CPP, 0); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_DEFAULT, RGB(0x00, 0x00, 0x00)); + SendMessage(newc, SCI_STYLECLEARALL,0, 0); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_COMMENT, RGB(0x00, 0x80, 0x00)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_COMMENTLINE, RGB(0x00, 0x80, 0x00)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_COMMENTDOC, RGB(0x00, 0x80, 0x00)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_NUMBER, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_WORD, RGB(0x00, 0x00, 0xFF)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_STRING, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_CHARACTER, RGB(0xA0, 0x10, 0x10)); +// SendMessage(newc, SCI_STYLESETFORE, SCE_C_UUID, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_PREPROCESSOR, RGB(0x00, 0x00, 0xFF)); +// SendMessage(newc, SCI_STYLESETFORE, SCE_C_OPERATOR, RGB(0x00, 0x00, 0x00)); +// SendMessage(newc, SCI_STYLESETFORE, SCE_C_IDENTIFIER, RGB(0x00, 0x00, 0x00)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_STRINGEOL, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_VERBATIM, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_REGEX, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_COMMENTLINEDOC, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_WORD2, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_COMMENTDOCKEYWORD, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_COMMENTDOCKEYWORDERROR, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_GLOBALCLASS, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_STRINGRAW, RGB(0xA0, 0x00, 0x00)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_TRIPLEVERBATIM, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_HASHQUOTEDSTRING, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_PREPROCESSORCOMMENT, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_PREPROCESSORCOMMENTDOC, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_USERLITERAL, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_TASKMARKER, RGB(0xA0, 0x10, 0x10)); + SendMessage(newc, SCI_STYLESETFORE, SCE_C_ESCAPESEQUENCE, RGB(0xA0, 0x10, 0x10)); + + SendMessage(newc, SCI_SETKEYWORDS, 0, (LPARAM) + "if else for do not while asm break case const continue " + "default entity enum enumflags extern " + "float goto int integer noref " + "nosave shared state optional string " + "struct switch thinktime until loop " + "typedef union var vector void " + "virtual nonvirtual class static nonstatic local return" + ); + + SendMessage(newc, SCI_SETPROPERTY, (WPARAM)"fold", (LPARAM)"1"); + SendMessage(newc, SCI_SETMOUSEDWELLTIME, 1000, 0); + SendMessage(newc, SCI_AUTOCSETORDER, SC_ORDER_PERFORMSORT, 0); + SendMessage(newc, SCI_AUTOCSETFILLUPS, 0, (LPARAM)".,[<>(*/+-=\t\n"); + + SendMessage(newc, SCI_SETMARGINSENSITIVEN, 1, (LPARAM)true); + } + else + { + //go to lucidia console, 10pt CHARFORMAT cf; memset(&cf, 0, sizeof(cf)); cf.cbSize = sizeof(cf); @@ -429,11 +732,11 @@ HWND CreateAnEditControl(HWND parent) cf.yHeight = 5; SendMessage(newc, EM_SETCHARFORMAT, SCF_ALL, (WPARAM)&cf); - } - - if (richedit) - { - SendMessage(newc, EM_EXLIMITTEXT, 0, 1<<20); + + if (richedit) + { + SendMessage(newc, EM_EXLIMITTEXT, 0, 1<<20); + } } if (!pDefSubclassProc || !pSetWindowSubclass) @@ -493,20 +796,6 @@ enum { IDM_FIRSTCHILD }; - -typedef struct editor_s { - char filename[MAX_PATH]; //abs - HWND window; - HWND editpane; - HWND tooltip; - char tooltiptext[1024]; - pbool modified; - time_t filemodifiedtime; - struct editor_s *next; -} editor_t; - -editor_t *editors; - void EditorReload(editor_t *editor); int EditorSave(editor_t *edit); void EditFile(char *name, int line); @@ -624,22 +913,39 @@ void EditorMenu(editor_t *editor, WPARAM wParam) } } -char *WordUnderCursor(editor_t *editor, char *buffer, int buffersize) +char *WordUnderCursor(editor_t *editor, char *buffer, int buffersize, int position) { unsigned char linebuf[1024]; DWORD charidx; DWORD lineidx; POINT pos; RECT rect; - GetCursorPos(&pos); - GetWindowRect(editor->editpane, &rect); - pos.x -= rect.left; - pos.y -= rect.top; - charidx = SendMessage(editor->editpane, EM_CHARFROMPOS, 0, (LPARAM)&pos); - lineidx = SendMessage(editor->editpane, EM_LINEFROMCHAR, charidx, 0); - charidx -= SendMessage(editor->editpane, EM_LINEINDEX, lineidx, 0); + if (editor->scintilla) + { + DWORD len; - Edit_GetLine(editor->editpane, lineidx, linebuf, sizeof(linebuf)); + lineidx = SendMessage(editor->editpane, SCI_LINEFROMPOSITION, position, 0); + charidx = position - SendMessage(editor->editpane, SCI_POSITIONFROMLINE, lineidx, 0); + + len = SendMessage(editor->editpane, SCI_LINELENGTH, lineidx, 0); + if (len >= sizeof(linebuf)) + return ""; + len = SendMessage(editor->editpane, SCI_GETLINE, lineidx, (LPARAM)linebuf); + linebuf[len] = 0; + if (charidx >= len) + charidx = len-1; + } + else + { + GetCursorPos(&pos); + GetWindowRect(editor->editpane, &rect); + pos.x -= rect.left; + pos.y -= rect.top; + charidx = SendMessage(editor->editpane, EM_CHARFROMPOS, 0, (LPARAM)&pos); + lineidx = SendMessage(editor->editpane, EM_LINEFROMCHAR, charidx, 0); + charidx -= SendMessage(editor->editpane, EM_LINEINDEX, lineidx, 0); + Edit_GetLine(editor->editpane, lineidx, linebuf, sizeof(linebuf)); + } //skip back to the start of the word while(charidx > 0 && ( @@ -671,12 +977,42 @@ char *WordUnderCursor(editor_t *editor, char *buffer, int buffersize) buffer[lineidx++] = 0; return buffer; } -char *GetTooltipText(editor_t *editor) + +pbool GenAutoCompleteList(char *prefix, char *buffer, int buffersize) +{ + QCC_def_t *def; + int prefixlen = strlen(prefix); + int usedbuffer = 0; + int l; + for (def = pr.def_head.next; def; def = def->next) + { + if (def->scope) + continue; //ignore locals, because we don't know where we are, and they're probably irrelevent. + + //make sure it has the right prefix + if (!strncmp(def->name, prefix, prefixlen)) + //but ignore it if its one of those special things that you're not meant to know about. + if (strcmp(def->name, "IMMEDIATE") && !strchr(def->name, ':') && !strchr(def->name, '.') && !strchr(def->name, '*') && !strchr(def->name, '[')) + { + l = strlen(def->name); + if (l && usedbuffer+2+l < buffersize) + { + if (usedbuffer) + buffer[usedbuffer++] = ' '; + memcpy(buffer+usedbuffer, def->name, l); + usedbuffer += l; + } + } + } + buffer[usedbuffer] = 0; + return usedbuffer>0; +} +char *GetTooltipText(editor_t *editor, int pos) { static char buffer[1024]; char wordbuf[256]; char *defname; - defname = WordUnderCursor(editor, wordbuf, sizeof(wordbuf)); + defname = WordUnderCursor(editor, wordbuf, sizeof(wordbuf), pos); if (!*defname) return NULL; else if (globalstable.numbuckets) @@ -686,7 +1022,7 @@ char *GetTooltipText(editor_t *editor) if (macro && *macro) return macro; - def = QCC_PR_GetDef(NULL, defname, NULL, false, 0, false); + def = QCC_PR_GetDef(NULL, defname, NULL, false, 0, GDF_SILENT); if (def) { char typebuf[1024]; @@ -761,7 +1097,7 @@ static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message, } goto gdefault; case WM_CREATE: - editor->editpane = CreateAnEditControl(hWnd); + editor->editpane = CreateAnEditControl(hWnd, &editor->scintilla); if (richedit) { SendMessage(editor->editpane, EM_EXLIMITTEXT, 0, 1<<31); @@ -795,6 +1131,7 @@ static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message, return TRUE; break; case WM_SETCURSOR: + if (!editor->scintilla) { POINT pos; char *newtext; @@ -803,7 +1140,7 @@ static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message, toolInfo.hwnd = hWnd; toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS | TTF_TRACK | TTF_ABSOLUTE; toolInfo.uId = (UINT_PTR)editor->editpane; - newtext = GetTooltipText(editor); + newtext = GetTooltipText(editor, -1); toolInfo.lpszText = editor->tooltiptext; if (!newtext) newtext = ""; @@ -829,7 +1166,7 @@ static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message, case WM_COMMAND: if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == editor->editpane) { - if (!editor->modified) + if (!editor->modified && !editor->scintilla) { char title[2048]; CHARRANGE chrg; @@ -841,10 +1178,11 @@ static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message, SendMessage(editor->editpane, EM_EXGETSEL, 0, (LPARAM) &chrg); + editor->curline = Edit_LineFromChar(editor->editpane, chrg.cpMin); if (editor->modified) - sprintf(title, "*%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, chrg.cpMin)); + sprintf(title, "*%s:%i - FTEQCC Editor", editor->filename, 1+editor->curline); else - sprintf(title, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, chrg.cpMin)); + sprintf(title, "%s:%i - FTEQCC Editor", editor->filename, 1+editor->curline); SetWindowText(editor->window, title); } } @@ -858,19 +1196,88 @@ static LRESULT CALLBACK EditorWndProc(HWND hWnd,UINT message, case WM_NOTIFY: { NMHDR *nmhdr; - SELCHANGE *sel; char title[2048]; + char *s; nmhdr = (NMHDR *)lParam; - switch(nmhdr->code) + if (editor->scintilla) { - case EN_SELCHANGE: - sel = (SELCHANGE *)nmhdr; + struct SCNotification *not = (struct SCNotification*)nmhdr; + int pos = SendMessage(editor->editpane, SCI_GETCURRENTPOS, 0, 0); + int l = SendMessage(editor->editpane, SCI_LINEFROMPOSITION, pos, 0); + int mode; + if (editor->curline != l) + editor->curline = l; + switch(nmhdr->code) + { + case SCN_MARGINCLICK: + /*fixme: should we scan the statements to ensure the line is valid? this applies to the f9 key too*/ + l = SendMessage(editor->editpane, SCI_LINEFROMPOSITION, not->position, 0); + mode = !(SendMessage(editor->editpane, SCI_MARKERGET, l, 0) & 1); + SendMessage(editor->editpane, mode?SCI_MARKERADD:SCI_MARKERDELETE, l, 0); + if (gamewindow) + { + enginewindow_t *e = (enginewindow_t*)(LONG_PTR)GetWindowLongPtr(gamewindow, GWLP_USERDATA); + EngineCommand(e, "qcbreakpoint %i \"%s\" %i\n", mode, editor->filename, l+1); + } + break; + case SCN_CHARADDED: + if (not->ch == '(') + { + char *s = GetTooltipText(editor, pos-1); + if (s) + SendMessage(editor->editpane, SCI_CALLTIPSHOW, (WPARAM)pos, (LPARAM)s); + } + else if (!SendMessage(editor->editpane, SCI_AUTOCACTIVE, 0, 0)) + { + char buffer[65536]; + char prefixbuffer[128]; + char *pre = WordUnderCursor(editor, prefixbuffer, sizeof(prefixbuffer), SendMessage(editor->editpane, SCI_GETCURRENTPOS, 0, 0)); + if (pre && *pre) + if (GenAutoCompleteList(pre, buffer, sizeof(buffer))) + SendMessage(editor->editpane, SCI_AUTOCSHOW, strlen(pre), (LPARAM)buffer); + } + break; + case SCN_SAVEPOINTREACHED: + editor->modified = false; + break; + case SCN_SAVEPOINTLEFT: + editor->modified = true; + + if (EditorModified(editor)) + if (MessageBox(NULL, "warning: file was modified externally. reload?", "Modified!", MB_YESNO) == IDYES) + EditorReload(editor); + break; + case SCN_DWELLSTART: + s = GetTooltipText(editor, not->position); + if (s) + SendMessage(editor->editpane, SCI_CALLTIPSHOW, (WPARAM)not->position, (LPARAM)s); + break; + case SCN_DWELLEND: + case SCN_FOCUSOUT: + SendMessage(editor->editpane, SCI_CALLTIPCANCEL, 0, 0); + break; + } if (editor->modified) - sprintf(title, "*%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin)); + sprintf(title, "*%s:%i - FTEQCC Editor", editor->filename, 1+editor->curline); else - sprintf(title, "%s:%i - FTEQCC Editor", editor->filename, 1+Edit_LineFromChar(editor->editpane, sel->chrg.cpMin)); + sprintf(title, "%s:%i - FTEQCC Editor", editor->filename, 1+editor->curline); SetWindowText(editor->window, title); - break; + } + else + { + SELCHANGE *sel; + switch(nmhdr->code) + { + case EN_SELCHANGE: + sel = (SELCHANGE *)nmhdr; + editor->curline = Edit_LineFromChar(editor->editpane, sel->chrg.cpMin); + if (editor->modified) + sprintf(title, "*%s:%i - FTEQCC Editor", editor->filename, 1+editor->curline); + else + sprintf(title, "%s:%i - FTEQCC Editor", editor->filename, 1+editor->curline); + SetWindowText(editor->window, title); + break; + } } } default: @@ -1235,38 +1642,49 @@ void EditorReload(editor_t *editor) QCC_ReadFile(editor->filename, file, flen); - file[flen] = 0; } else file = NULL; - SendMessage(editor->editpane, EM_SETEVENTMASK, 0, 0); - - /*clear it out*/ - Edit_SetSel(editor->editpane,0,Edit_GetTextLength(editor->editpane)); - Edit_ReplaceSel(editor->editpane,""); - - if (file) - { - char msg[1024]; - wchar_t *ch = QCC_makeutf16(file, flen, NULL); - Edit_SetSel(editor->editpane,0,0); - SetWindowTextW(editor->editpane, ch); - /*if (errors) - { - QC_snprintfz(msg, sizeof(msg), "%s contains encoding errors. Invalid bytes have been converted to the 0xe000 private use area.", editor->filename); - MessageBox(editor->editpane, msg, "Encoding errors.", MB_ICONWARNING); - }*/ - free(ch); - free(file); - } - - editor->modified = false; stat(editor->filename, &sbuf); editor->filemodifiedtime = sbuf.st_mtime; - SendMessage(editor->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE|ENM_CHANGE); + if (editor->scintilla) + { +// SendMessage(editor->editpane, SCI_SETUNDOCOLLECTION, 0, 0); + SendMessage(editor->editpane, SCI_SETTEXT, 0, (LPARAM)file); +// SendMessage(editor->editpane, SCI_SETUNDOCOLLECTION, 1, 0); + SendMessage(editor->editpane, EM_EMPTYUNDOBUFFER, 0, 0); + SendMessage(editor->editpane, SCI_SETSAVEPOINT, 0, 0); + } + else + { + SendMessage(editor->editpane, EM_SETEVENTMASK, 0, 0); + + /*clear it out*/ + Edit_SetSel(editor->editpane,0,Edit_GetTextLength(editor->editpane)); + Edit_ReplaceSel(editor->editpane,""); + + if (file) + { +// char msg[1024]; + wchar_t *ch = QCC_makeutf16(file, flen, NULL); + Edit_SetSel(editor->editpane,0,0); + SetWindowTextW(editor->editpane, ch); + /*if (errors) + { + QC_snprintfz(msg, sizeof(msg), "%s contains encoding errors. Invalid bytes have been converted to the 0xe000 private use area.", editor->filename); + MessageBox(editor->editpane, msg, "Encoding errors.", MB_ICONWARNING); + }*/ + free(ch); + } + SendMessage(editor->editpane, EM_SETEVENTMASK, 0, ENM_SELCHANGE|ENM_CHANGE); + } + + free(file); + + editor->modified = false; } void EditFile(char *name, int line) @@ -1379,6 +1797,7 @@ void EditFile(char *name, int line) MessageBox(NULL, "Failed to create editor window", "Error", 0); return; } + SetWindowLongPtr(neweditor->window, GWLP_USERDATA, (LONG_PTR)neweditor); EditorReload(neweditor); @@ -1402,18 +1821,33 @@ int EditorSave(editor_t *edit) struct stat sbuf; int len; wchar_t *file; - len = GetWindowTextLengthW(edit->editpane); - file = malloc((len+1)*2); - if (!file) + if (edit->scintilla) { - MessageBox(NULL, "Save failed - not enough mem", "Error", 0); - return false; + len = SendMessage(edit->editpane, SCI_GETLENGTH, 0, 0)+1; + file = malloc(len); + SendMessage(edit->editpane, SCI_GETTEXT, len, (LPARAM)file); + if (!QCC_WriteFile(edit->filename, file, len)) + { + MessageBox(NULL, "Save failed\nCheck path and ReadOnly flags", "Failure", 0); + return false; + } + SendMessage(edit->editpane, SCI_SETSAVEPOINT, 0, 0); } - GetWindowTextW(edit->editpane, file, len+1); - if (!QCC_WriteFileW(edit->filename, file, len)) + else { - MessageBox(NULL, "Save failed\nCheck path and ReadOnly flags", "Failure", 0); - return false; + len = GetWindowTextLengthW(edit->editpane); + file = malloc((len+1)*2); + if (!file) + { + MessageBox(NULL, "Save failed - not enough mem", "Error", 0); + return false; + } + GetWindowTextW(edit->editpane, file, len+1); + if (!QCC_WriteFileW(edit->filename, file, len)) + { + MessageBox(NULL, "Save failed\nCheck path and ReadOnly flags", "Failure", 0); + return false; + } } free(file); @@ -1443,8 +1877,33 @@ char *GUIReadFile(const char *fname, void *buffer, int blen) { // int elen = GetWindowTextLengthW(e->editpane); //our qcc itself is fine with utf-16, so long as it has a BOM. - *(short*)buffer = 0xfeff; - GetWindowTextW(e->editpane, (short*)buffer+1, blen); + if (e->scintilla) + { + SendMessage(e->editpane, SCI_GETTEXT, blen, (LPARAM)buffer); + } + else + { + *(wchar_t*)buffer = 0xfeff; + GetWindowTextW(e->editpane, (wchar_t*)buffer+1, blen); + } + + if (e->modified) + { + if (EditorModified(e)) + { + if (MessageBox(e->window, "File was modified on disk. Overwrite?", e->filename, MB_YESNO) == IDYES) + { + if (e->scintilla) + { + QCC_WriteFile(e->filename, buffer, blen); + SendMessage(e->editpane, SCI_SETSAVEPOINT, 0, 0); //tell the control that it was saved. + } + else + QCC_WriteFileW(e->filename, (wchar_t*)buffer+1, blen); + } + } + } + return buffer; } } @@ -1459,7 +1918,11 @@ int GUIFileSize(const char *fname) { if (e->window && !strcmp(e->filename, fname)) { - int len = (GetWindowTextLengthW(e->editpane)+1)*2; + int len; + if (e->scintilla) + len = SendMessage(e->editpane, SCI_GETLENGTH, 0, 0)+1; + else + len = (GetWindowTextLengthW(e->editpane)+1)*2; return len; } } @@ -1477,43 +1940,98 @@ pbool EditorModified(editor_t *e) return false; } - - - -//the engine thread simply sits waiting for responses from the engine -typedef struct +char *COM_ParseOut (const char *data, char *out, int outlen) { - int pipeclosed; - DWORD tid; - HWND window; - HANDLE thread; - HANDLE pipefromengine; - HANDLE pipetoengine; -} enginewindow_t; + int c; + int len; -void EngineCommand(enginewindow_t *ctx, char *message, ...) -{ - //qcresume - resume running - //qcinto - singlestep. execute-with-debugging child functions - //qcover - singlestep. execute-without-debugging child functions - //qcout - singlestep. leave current function and enter parent. - //qcbreak "$loc" - set breakpoint - //qcwatch "$var" - set watchpoint - //qcstack - force-report stack trace - va_list va; - char finalmessage[1024]; - va_start (va, message); - vsnprintf (finalmessage, sizeof(finalmessage)-1, message, va); - va_end (va); - if (ctx->pipetoengine) + len = 0; + out[0] = 0; + + if (!data) + return NULL; + +// skip whitespace +skipwhite: + while ( (c = *data) <= ' ') { - DWORD written = 0; - WriteFile(ctx->pipetoengine, finalmessage, strlen(finalmessage), &written, NULL); + if (c == 0) + return NULL; // end of file; + data++; } + +// skip // comments + if (c=='/') + { + if (data[1] == '/') + { + while (*data && *data != '\n') + data++; + goto skipwhite; + } + } + +//skip / * comments + if (c == '/' && data[1] == '*') + { + data+=2; + while(*data) + { + if (*data == '*' && data[1] == '/') + { + data+=2; + goto skipwhite; + } + data++; + } + goto skipwhite; + } + +// handle quoted strings specially + if (c == '\"') + { + data++; + while (1) + { + if (len >= outlen-1) + { + out[len] = 0; + return (char*)data; + } + + c = *data++; + if (c=='\"' || !c) + { + out[len] = 0; + return (char*)data; + } + out[len] = c; + len++; + } + } + +// parse a regular word + do + { + if (len >= outlen-1) + { + out[len] = 0; + return (char*)data; + } + + out[len] = c; + data++; + len++; + c = *data; + } while (c>32); + + out[len] = 0; + return (char*)data; } unsigned int WINAPI threadwrapper(void *args) { + static char filenamebuffer[256]; enginewindow_t *ctx = args; { PROCESS_INFORMATION childinfo; @@ -1536,7 +2054,7 @@ unsigned int WINAPI threadwrapper(void *args) SetHandleInformation(ctx->pipefromengine, HANDLE_FLAG_INHERIT, 0); SetHandleInformation(ctx->pipetoengine, HANDLE_FLAG_INHERIT, 0); - EngineCommand(ctx, "vid_recenter %i %i %i %i %#p\n", 0, 0, 640, 480, (void*)ctx->window); +// EngineCommand(ctx, "vid_recenter %i %i %i %i %#p\n", 0, 0, 640, 480, (void*)ctx->window); CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, enginebasedir, &startinfo, &childinfo); @@ -1590,21 +2108,25 @@ unsigned int WINAPI threadwrapper(void *args) //stack "$func" "$loc" //local $depth } - else if (!strncmp(buffer, "qcstep ", 5)) + else if (!strncmp(buffer, "qcstep ", 7)) { - //qcvm stepped to the line specified, often dupes - //qcstep "$location" - EngineCommand(ctx, "qcstep\n"); //moves on to the next statement + //post it, because of thread ownership issues. + char *l = COM_ParseOut(buffer+7, filenamebuffer, sizeof(filenamebuffer)); + if (*l == ':') + l++; + while(*l == ' ') + l++; + PostMessage(ctx->window, WM_USER, atoi(l), (LPARAM)filenamebuffer); //and tell the owning window to try to close it again } else if (!strncmp(buffer, "qcvalue ", 6)) { //qcvalue "$variableformula" "$value" } - else if (!strncmp(buffer, "qcreloaded ", 6)) + else if (!strncmp(buffer, "qcreloaded ", 10)) { //so we can resend any breakpoint commands //qcreloaded "$vmname" "$progsname" - EngineCommand(ctx, "qcresume\n"); + PostMessage(ctx->window, WM_USER+1, 0, 0); //and tell the owning window to try to close it again } else { @@ -1631,6 +2153,7 @@ static LRESULT CALLBACK EngineWndProc(HWND hWnd,UINT message, WPARAM wParam,LPARAM lParam) { enginewindow_t *e; + editor_t *editor; switch (message) { case WM_CREATE: @@ -1667,6 +2190,32 @@ static LRESULT CALLBACK EngineWndProc(HWND hWnd,UINT message, if (hWnd == gamewindow) gamewindow = NULL; break; + case WM_USER: + //engine broke. show code. + EditFile((char*)lParam, wParam-1); + break; + case WM_USER+1: + //engine loaded a progs, reset breakpoints. + e = (enginewindow_t*)(LONG_PTR)GetWindowLongPtr(gamewindow, GWLP_USERDATA); + for (editor = editors; editor; editor = editor->next) + { + int line = -1; + if (!editor->scintilla) + continue; + + for (;;) + { + line = SendMessage(editor->editpane, SCI_MARKERNEXT, line, 1); + if (line == -1) + break; //no more. + line++; + + EngineCommand(e, "qcbreakpoint 1 \"%s\" %i\n", editor->filename, line); + } + } + //and now let the engine continue + EngineCommand(e, "qcresume\n"); + break; default: gdefault: @@ -1706,13 +2255,13 @@ void RunEngine(void) mcs.lParam = 0; gamewindow = (HWND) SendMessage (mdibox, WM_MDICREATE, 0, (LONG_PTR) (LPMDICREATESTRUCT) &mcs); - ShowWindow(gamewindow, SW_SHOW); + // ShowWindow(gamewindow, SW_SHOW); } else { enginewindow_t *e = (enginewindow_t*)(LONG_PTR)GetWindowLongPtr(gamewindow, GWLP_USERDATA); } - SendMessage(mdibox, WM_MDIACTIVATE, (WPARAM)gamewindow, 0); +// SendMessage(mdibox, WM_MDIACTIVATE, (WPARAM)gamewindow, 0); } @@ -1769,6 +2318,10 @@ static LRESULT CALLBACK OptionsWndProc(HWND hWnd,UINT message, Edit_GetText(w_enginebinary, enginebinary, sizeof(enginebinary)-1); Edit_GetText(w_enginebasedir, enginebasedir, sizeof(enginebasedir)-1); Edit_GetText(w_enginecommandline, enginecommandline, sizeof(enginecommandline)-1); + + QCC_RegSetValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginebinary", REG_SZ, enginebinary, strlen(enginebinary)); + QCC_RegSetValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginebasedir", REG_SZ, enginebasedir, strlen(enginebasedir)); + QCC_RegSetValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginecommandline", REG_SZ, enginecommandline, strlen(enginecommandline)); #endif if (wParam == IDI_O_USE) @@ -2456,7 +3009,7 @@ static LRESULT CALLBACK OutputWindowProc(HWND hWnd,UINT message, outputbox = NULL; break; case WM_CREATE: - outputbox = CreateAnEditControl(hWnd); + outputbox = CreateAnEditControl(hWnd, NULL); case WM_SIZE: GetClientRect(hWnd, &rect); SetWindowPos(outputbox, NULL, 0, 0, rect.right-rect.left, rect.bottom-rect.top, 0); @@ -2706,7 +3259,7 @@ void RunCompiler(char *args) if (gamewindow) { enginewindow_t *e = (enginewindow_t*)(LONG_PTR)GetWindowLongPtr(gamewindow, GWLP_USERDATA); - EngineCommand(e, "restart\n"); + EngineCommand(e, "qcresume\nmenu_restart\nrestart\n"); } } @@ -2926,6 +3479,13 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin GUI_SetDefaultOpts(); + if (!QCC_RegGetStringValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginebinary", enginebinary, sizeof(enginebinary))) + strcpy(enginebinary, "fteglqw.exe"); + if (!QCC_RegGetStringValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginebasedir", enginebasedir, sizeof(enginebasedir))) + strcpy(enginebasedir, "../.."); + if (!QCC_RegGetStringValue(HKEY_CURRENT_USER, "Software\\FTE QuakeWorld\\fteqccgui", "enginecommandline", enginecommandline, sizeof(enginecommandline))) + strcpy(enginecommandline, "-window +map start -nohome"); + if(strstr(lpCmdLine, "-stdout")) { GUI_ParseCommandLine(lpCmdLine); @@ -3063,7 +3623,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin */ if (!mdibox) - outputbox = CreateAnEditControl(mainwindow); + outputbox = CreateAnEditControl(mainwindow, NULL); for (i = 0; i < NUMBUTTONS; i++) { @@ -3172,6 +3732,8 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin else if (!strncmp(line, "Including: ", 11)) EditFile(line+11, -1); } + else if (!strncmp(line, "including ", 10)) + EditFile(line+10, -1); else if (!strncmp(line, "compiling ", 10)) EditFile(line+10, -1); else if (!strncmp(line, "prototyping ", 12)) diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 662014e06..e01ce2f44 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -242,6 +242,7 @@ optimisations_t optimisations[] = {&opt_stripfunctions, "sf", 3, FLAG_KILLSDEBUGGERS, "strip_functions", "Strips out the 'defs' of functions that were only ever called directly. This does not affect saved games. This can affect FTE_MULTIPROGS."}, {&opt_locals_overlapping, "lo", 3, FLAG_KILLSDEBUGGERS, "locals_overlapping", "Store all locals in a single section of the pr_globals. Vastly reducing it. This effectivly does the job of overlaptemps.\nHowever, locals are no longer automatically initialised to 0 (and never were in the case of recursion, but at least then its the same type).\nIf locals appear uninitialised, fteqcc will disable this optimisation for the affected functions, you can optionally get a warning about these locals using: #pragma warning enable F302"}, {&opt_vectorcalls, "vc", 4, FLAG_KILLSDEBUGGERS, "vectorcalls", "Where a function is called with just a vector, this causes the function call to store three floats instead of one vector. This can save a good number of pr_globals where those vectors contain many duplicate coordinates but do not match entirly."}, + {&opt_classfields, "cf", 2, FLAG_KILLSDEBUGGERS, "class_fields", "Strip class field names. This will harm debugging and can result in 'gibberish' names appearing in saved games. Has no effect on engines other than FTEQW, which will not recognise these anyway."}, {NULL} }; @@ -3070,7 +3071,7 @@ int qcc_compileactive = false; extern int accglobalsblock; extern int qcc_debugflag; char *originalqccmsrc; //for autoprototype. -void QCC_main (int argc, char **argv) //as part of the quake engine +pbool QCC_main (int argc, char **argv) //as part of the quake engine { extern int pr_bracelevel, tempsused; time_t long_time; @@ -3083,6 +3084,15 @@ void QCC_main (int argc, char **argv) //as part of the quake engine #endif char *s; + if (numsourcefiles && currentsourcefile == numsourcefiles) + { + numsourcefiles = 0; + return false; + } + + if (!PreCompile()) + return false; + SetEndian(); myargc = argc; @@ -3292,7 +3302,7 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string)); printf ("-Fsubscope to make locals specific to their subscope\n"); qcc_compileactive = false; - return; + return true; } if (flag_caseinsensitive) @@ -3353,7 +3363,7 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string)); qcc_compileactive = false; numsourcefiles = 0; currentsourcefile = 0; - return; + return true; } if (currentsourcefile) @@ -3364,7 +3374,7 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string)); if (QCC_LoadFile (qccmprogsdat, (void *)&qccmsrc) == -1) { - return; + return true; } } @@ -3402,7 +3412,7 @@ newstyle: newstylesource = true; originalqccmsrc = qccmsrc; StartNewStyleCompile(); - return; + return true; } pr_file_p = qccmsrc; @@ -3473,7 +3483,7 @@ newstyle: { printf("No changes\n"); qcc_compileactive = false; - return; + return true; } else { @@ -3489,6 +3499,7 @@ newstyle: currentchunk = NULL; originalqccmsrc = qccmsrc; + return true; } void new_QCC_ContinueCompile(void); @@ -3531,9 +3542,8 @@ void QCC_ContinueCompile(void) if (currentsourcefile < numsourcefiles) { - if (!PreCompile()) + if (!QCC_main(myargc, myargv)) return; - QCC_main(myargc, myargv); } else { @@ -3773,9 +3783,8 @@ void new_QCC_ContinueCompile(void) QCC_FinishCompile(); PostCompile(); - if (!PreCompile()) + if (!QCC_main(myargc, myargv)) return; - QCC_main(myargc, myargv); return; } } diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index 461a2ec24..2ced448fe 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -1146,7 +1146,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) { ssqc_deprecated_warned = true; Con_Printf("NQWriteByte: invalid tempentity %i. Future errors will be dprinted. You may need to enable sv_csqcdebug.\n", data); - PR_StackTrace(svprogfuncs); + PR_StackTrace(svprogfuncs, false); } else Con_DPrintf("NQWriteByte: unknown tempentity %i\n", data); diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index ee47e8067..8f0004e57 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -221,7 +221,7 @@ pbool PDECL ED_CanFree (edict_t *ed) if (developer.value) { Con_TPrintf("cannot free world entity\n"); - PR_StackTrace(svprogfuncs); + PR_StackTrace(svprogfuncs, false); svprogfuncs->pr_trace = 1; } return false; @@ -229,7 +229,7 @@ pbool PDECL ED_CanFree (edict_t *ed) if (NUM_FOR_EDICT(svprogfuncs, ed) <= sv.allocated_client_slots) { Con_TPrintf("cannot free player entities\n"); - PR_StackTrace(svprogfuncs); + PR_StackTrace(svprogfuncs, false); svprogfuncs->pr_trace = 1; return false; } @@ -443,61 +443,6 @@ void QC_Clear(void); builtin_t pr_builtin[]; extern int pr_numbuiltins; -int QCLibEditor(pubprogfuncs_t *prinst, char *filename, int line, int statement, int nump, char **parms); -int QDECL QCEditor (pubprogfuncs_t *prinst, char *filename, int line, int statement, int nump, char **parms) -{ -#ifdef TEXTEDITOR - static char oldfuncname[64]; - - if (!parms) - return QCLibEditor(prinst, filename, line, statement, nump, parms); - else - { - if (!nump && !strncmp(oldfuncname, *parms, sizeof(oldfuncname))) - { - Con_Printf("Executing %s: %s\n", *parms, filename); - Q_strncpyz(oldfuncname, *parms, sizeof(oldfuncname)); - } - return line; - } -#else - int i; - char buffer[8192]; - char *r; - vfsfile_t *f; - - if (line == -1) - return line; - SV_EndRedirect(); - if (developer.value) - { - f = FS_OpenVFS(filename, "rb", FS_GAME); - } - else - f = NULL; //faster. - if (!f) - { - Q_snprintfz(buffer, sizeof(buffer), "%s/%s", pr_sourcedir.string, filename); - f = FS_OpenVFS(buffer, "rb", FS_GAME); - } - if (!f) - Con_Printf("-%s - %i\n", filename, line); - else - { - for (i = 0; i < line; i++) - { - VFS_GETS(f, buffer, sizeof(buffer)); - } - if ((r = strchr(buffer, '\r'))) - { r[0] = '\n';r[1]='\0';} - Con_Printf("-%s", buffer); - VFS_CLOSE(f); - } -//PF_break(NULL); - return line; -#endif -} - model_t *SVPR_GetCModel(world_t *w, int modelindex) { if ((unsigned int)modelindex < MAX_MODELS) @@ -2245,7 +2190,7 @@ static void QCBUILTIN PF_objerror (pubprogfuncs_t *prinst, struct globalvars_s * else { ED_Free (prinst, ed); - PR_StackTrace(prinst); + PR_StackTrace(prinst, true); PR_AbortStack(prinst); } @@ -3681,7 +3626,7 @@ static void QCBUILTIN PF_Remove (pubprogfuncs_t *prinst, struct globalvars_s *pr if (developer.value) { Con_Printf("Tried removing free entity at:\n"); - PR_StackTrace(prinst); + PR_StackTrace(prinst, false); } return; //yeah, alright, so this is hacky. } @@ -8965,7 +8910,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"changelevel", PF_Fixme, 0, 0, 0, 64, "void(string map)"}, {"localsound", PF_Fixme, 0, 0, 0, 65, "void(string sample)"}, {"getmousepos", PF_Fixme, 0, 0, 0, 66, "vector()"}, - {"gettime", PF_Fixme, 0, 0, 0, 67, "float()"}, + {"gettime", PF_Fixme, 0, 0, 0, 67, "float(optional float timetype)"}, {"loadfromdata", PF_Fixme, 0, 0, 0, 68, "void(string data)"}, {"loadfromfile", PF_Fixme, 0, 0, 0, 69, "void(string data)"}, {"mod", PF_Fixme, 0, 0, 0, 70, "float(float val, float m)"}, @@ -8987,6 +8932,10 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"findflags", PF_Fixme, 0, 0, 0, 87, "entity(entity start, .float field, float match)"}, {"findchainflags", PF_Fixme, 0, 0, 0, 88, "entity(.float field, float match)"}, {"mcvar_defstring", PF_Fixme, 0, 0, 0, 89, "string(string name)" STUB}, + + {"setmodel", PF_Fixme, 0, 0, 0, 90, D("void(entity ent, string mname)", "Menuqc-specific version.")}, + {"precache_model", PF_Fixme, 0, 0, 0, 91, D("void(string mname)", "Menuqc-specific version.")}, + {"setorigin", PF_Fixme, 0, 0, 0, 92, D("void(entity ent, vector neworg)","Menuqc-specific version.")}, //end menu-only 'standard' #endif //nq qw h2 ebfs @@ -9669,7 +9618,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"argv_end_index", PF_argv_end_index, 0, 0, 0, 516, "float(float idx)"}, {"buf_cvarlist", PF_buf_cvarlist, 0, 0, 0, 517, "void(float strbuf)"}, {"cvar_description",PF_cvar_description,0, 0, 0, 518, "string(string cvarname)"}, - {"gettime", PF_Fixme, 0, 0, 0, 519, "float(optional float timetype)"}, + {"gettime", PF_gettime, 0, 0, 0, 519, "float(optional float timetype)"}, {"keynumtostring_omgwtf",PF_Fixme, 0, 0, 0, 520, "string(float keynum)"}, //excessive third version in dp's csqc. {"findkeysforcommand",PF_Fixme, 0, 0, 0, 521, "string(string command, optional float bindmap)"}, // {"initparticlespawner",PF_Fixme, 0, 0, 0, 522, "void(float max_themes)"}, @@ -10575,24 +10524,24 @@ void PR_DumpPlatform_f(void) {"STAT_VIEW2", "const float", CS, "This stat contains the number of the entity in the server's .view2 field.", STAT_VIEW2}, {"STAT_VIEWZOOM", "const float", CS, NULL, STAT_VIEWZOOM}, - {"VF_MIN", "const float", CS, "The top-left of the 3d viewport in screenspace. The VF_ values are used via the setviewprop/getviewprop builtins.", VF_MIN}, - {"VF_MIN_X", "const float", CS, NULL, VF_MIN_X}, - {"VF_MIN_Y", "const float", CS, NULL, VF_MIN_Y}, - {"VF_SIZE", "const float", CS, "The width+height of the 3d viewport in screenspace.", VF_SIZE}, - {"VF_SIZE_X", "const float", CS, NULL, VF_SIZE_X}, - {"VF_SIZE_Y", "const float", CS, NULL, VF_SIZE_Y}, - {"VF_VIEWPORT", "const float", CS, "vector+vector. Two argument shortcut for VF_MIN and VF_SIZE", VF_VIEWPORT}, - {"VF_FOV", "const float", CS, "sets both fovx and fovy. consider using afov instead.", VF_FOV}, - {"VF_FOVX", "const float", CS, "horizontal field of view. does not consider aspect at all.", VF_FOVX}, - {"VF_FOVY", "const float", CS, "vertical field of view. does not consider aspect at all.", VF_FOVY}, - {"VF_ORIGIN", "const float", CS, "The origin of the view. Not of the player.", VF_ORIGIN}, - {"VF_ORIGIN_X", "const float", CS, NULL, VF_ORIGIN_X}, - {"VF_ORIGIN_Y", "const float", CS, NULL, VF_ORIGIN_Y}, - {"VF_ORIGIN_Z", "const float", CS, NULL, VF_ORIGIN_Z}, - {"VF_ANGLES", "const float", CS, "The angles the view will be drawn at. Not the angle the client reports to the server.", VF_ANGLES}, - {"VF_ANGLES_X", "const float", CS, NULL, VF_ANGLES_X}, - {"VF_ANGLES_Y", "const float", CS, NULL, VF_ANGLES_Y}, - {"VF_ANGLES_Z", "const float", CS, NULL, VF_ANGLES_Z}, + {"VF_MIN", "const float", CS|MENU, "The top-left of the 3d viewport in screenspace. The VF_ values are used via the setviewprop/getviewprop builtins.", VF_MIN}, + {"VF_MIN_X", "const float", CS|MENU, NULL, VF_MIN_X}, + {"VF_MIN_Y", "const float", CS|MENU, NULL, VF_MIN_Y}, + {"VF_SIZE", "const float", CS|MENU, "The width+height of the 3d viewport in screenspace.", VF_SIZE}, + {"VF_SIZE_X", "const float", CS|MENU, NULL, VF_SIZE_X}, + {"VF_SIZE_Y", "const float", CS|MENU, NULL, VF_SIZE_Y}, + {"VF_VIEWPORT", "const float", CS|MENU, "vector+vector. Two argument shortcut for VF_MIN and VF_SIZE", VF_VIEWPORT}, + {"VF_FOV", "const float", CS|MENU, "sets both fovx and fovy. consider using afov instead.", VF_FOV}, + {"VF_FOVX", "const float", CS|MENU, "horizontal field of view. does not consider aspect at all.", VF_FOVX}, + {"VF_FOVY", "const float", CS|MENU, "vertical field of view. does not consider aspect at all.", VF_FOVY}, + {"VF_ORIGIN", "const float", CS|MENU, "The origin of the view. Not of the player.", VF_ORIGIN}, + {"VF_ORIGIN_X", "const float", CS|MENU, NULL, VF_ORIGIN_X}, + {"VF_ORIGIN_Y", "const float", CS|MENU, NULL, VF_ORIGIN_Y}, + {"VF_ORIGIN_Z", "const float", CS|MENU, NULL, VF_ORIGIN_Z}, + {"VF_ANGLES", "const float", CS|MENU, "The angles the view will be drawn at. Not the angle the client reports to the server.", VF_ANGLES}, + {"VF_ANGLES_X", "const float", CS|MENU, NULL, VF_ANGLES_X}, + {"VF_ANGLES_Y", "const float", CS|MENU, NULL, VF_ANGLES_Y}, + {"VF_ANGLES_Z", "const float", CS|MENU, NULL, VF_ANGLES_Z}, {"VF_DRAWWORLD", "const float", CS, "boolean. If set to 1, the engine will draw the world and static/persistant rtlights. If 0, the world will be skipped and everything will be fullbright.", VF_DRAWWORLD}, {"VF_DRAWENGINESBAR", "const float", CS, "boolean. If set to 1, the sbar will be drawn, and viewsize will be honoured automatically.", VF_ENGINESBAR}, {"VF_DRAWCROSSHAIR", "const float", CS, "boolean. If set to 1, the engine will draw its default crosshair.", VF_DRAWCROSSHAIR}, @@ -10602,22 +10551,22 @@ void PR_DumpPlatform_f(void) {"VF_CL_VIEWANGLES_Y", "const float", CS, NULL, VF_CL_VIEWANGLES_Y}, {"VF_CL_VIEWANGLES_Z", "const float", CS, NULL, VF_CL_VIEWANGLES_Z}, - {"VF_PERSPECTIVE", "const float", CS, "1: regular rendering. Fov specifies the angle. 0: isometric-style. Fov specifies the number of Quake Units each side of the viewport.", VF_PERSPECTIVE}, + {"VF_PERSPECTIVE", "const float", CS|MENU, "1: regular rendering. Fov specifies the angle. 0: isometric-style. Fov specifies the number of Quake Units each side of the viewport.", VF_PERSPECTIVE}, {"VF_LPLAYER", "const float", CS, "The 'seat' number, used when running splitscreen.", VF_LPLAYER}, - {"VF_AFOV", "const float", CS, "Aproximate fov. Matches the 'fov' cvar. The engine handles the aspect ratio for you.", VF_AFOV}, - {"VF_SCREENVSIZE", "const float", CS, "Provides a reliable way to retrieve the current virtual screen size (even if the screen is automatically scaled to retain aspect).", VF_SCREENVSIZE}, - {"VF_SCREENPSIZE", "const float", CS, "Provides a reliable way to retrieve the current physical screen size (cvars need vid_restart for them to take effect).", VF_SCREENPSIZE}, + {"VF_AFOV", "const float", CS|MENU, "Aproximate fov. Matches the 'fov' cvar. The engine handles the aspect ratio for you.", VF_AFOV}, + {"VF_SCREENVSIZE", "const float", CS|MENU, "Provides a reliable way to retrieve the current virtual screen size (even if the screen is automatically scaled to retain aspect).", VF_SCREENVSIZE}, + {"VF_SCREENPSIZE", "const float", CS|MENU, "Provides a reliable way to retrieve the current physical screen size (cvars need vid_restart for them to take effect).", VF_SCREENPSIZE}, {"VF_VIEWENTITY", "const float", CS, "Changes the RF_EXTERNALMODEL flag on entities to match the new selection, and removes entities flaged with RF_VIEWENTITY. Requires cunning use of .entnum and typically requires calling addentities(MASK_VIEWMODEL) too.", VF_VIEWENTITY}, - {"VF_RT_DESTCOLOUR", "const float", CS, "The FrameBuffer texture index to write colour info into. 1-based. Additional arguments are: format (rgba8=1,rgba16f=2,rgba32f=3), sizexy. Written to by both 3d and 2d rendering.", VF_RT_DESTCOLOUR}, - {"VF_RT_SOURCECOLOUR", "const float", CS, "The FrameBuffer texture index to use with shaders that specify a $sourcecolour map.", VF_RT_SOURCECOLOUR}, - {"VF_RT_DEPTH", "const float", CS, "The FrameBuffer texture index to use as a depth buffer. Also used for shaders that specify $sourcedepth. 1-based. Additional arguments are: format (16=4,24=5,32=6), sizexy.", VF_RT_DEPTH}, - {"VF_RT_RIPPLE", "const float", CS, "The FrameBuffer texture index to use as a ripplemap (target for shaders with 'sort ripple'). Also used for shaders that specify $ripplemap. 1-based. Additional arguments are: format, sizexy.", VF_RT_RIPPLE}, + {"VF_RT_DESTCOLOUR", "const float", CS|MENU, "The FrameBuffer texture index to write colour info into. 1-based. Additional arguments are: format (rgba8=1,rgba16f=2,rgba32f=3), sizexy. Written to by both 3d and 2d rendering.", VF_RT_DESTCOLOUR}, + {"VF_RT_SOURCECOLOUR", "const float", CS|MENU, "The FrameBuffer texture index to use with shaders that specify a $sourcecolour map.", VF_RT_SOURCECOLOUR}, + {"VF_RT_DEPTH", "const float", CS|MENU, "The FrameBuffer texture index to use as a depth buffer. Also used for shaders that specify $sourcedepth. 1-based. Additional arguments are: format (16=4,24=5,32=6), sizexy.", VF_RT_DEPTH}, + {"VF_RT_RIPPLE", "const float", CS|MENU, "The FrameBuffer texture index to use as a ripplemap (target for shaders with 'sort ripple'). Also used for shaders that specify $ripplemap. 1-based. Additional arguments are: format, sizexy.", VF_RT_RIPPLE}, {"RF_VIEWMODEL", "const float", CS, "Specifies that the entity is a view model, and that its origin is relative to the current view position. These entities are also subject to viewweapon bob.", CSQCRF_VIEWMODEL}, {"RF_EXTERNALMODEL", "const float", CS, "Specifies that this entity should be displayed in mirrors (and may still cast shadows), but will not otherwise be visible.", CSQCRF_EXTERNALMODEL}, - {"RF_DEPTHHACK", "const float", CS, "Hacks the depth values such that the entity uses depth values as if it were closer to the screen. This is useful when combined with viewmodels to avoid weapons poking in to walls.", CSQCRF_DEPTHHACK}, - {"RF_ADDITIVE", "const float", CS, "Shaders from this entity will temporarily be hacked to use an additive blend mode instead of their normal blend mode.", CSQCRF_ADDITIVE}, + {"RF_DEPTHHACK", "const float", CS|MENU, "Hacks the depth values such that the entity uses depth values as if it were closer to the screen. This is useful when combined with viewmodels to avoid weapons poking in to walls.", CSQCRF_DEPTHHACK}, + {"RF_ADDITIVE", "const float", CS|MENU, "Shaders from this entity will temporarily be hacked to use an additive blend mode instead of their normal blend mode.", CSQCRF_ADDITIVE}, {"RF_USEAXIS", "const float", CS, "The entity will be oriented according to the current v_forward+v_right+v_up vector values instead of the entity's .angles field.", CSQCRF_USEAXIS}, {"RF_NOSHADOW", "const float", CS, "This entity will not cast shadows. Often useful on view models.", CSQCRF_NOSHADOW}, {"RF_FRAMETIMESARESTARTTIMES","const float", CS, "Specifies that the frame1time, frame2time field are timestamps (denoting the start of the animation) rather than time into the animation.", CSQCRF_FRAMETIMESARESTARTTIMES}, diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index a5c4fc706..274ce66a3 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -1029,7 +1029,7 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_ MSG_WriteByte(msg, state->skinnum); } if (bits & UF_COLORMAP) - MSG_WriteByte(msg, state->colormap); + MSG_WriteByte(msg, state->colormap & 0xff); if (bits & UF_SOLID) MSG_WriteShort(msg, state->solid); diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 729dcf317..847b86c0f 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -574,6 +574,8 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int case MULTICAST_PVS: to = MULTICAST_ALL; break; + default: + break; } }