diff --git a/engine/client/image.c b/engine/client/image.c index dfddefff..8eaa1edb 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -2285,8 +2285,8 @@ static void Image_LoadTextureMips(void *ctx, void *data, size_t a, size_t b) texid_t tex = ctx; struct pendingtextureinfo *mips = data; - tex->width = mips->mip[0].width; - tex->height = mips->mip[0].height; +// tex->width = mips->mip[0].width; +// tex->height = mips->mip[0].height; if (rf->IMG_LoadTextureMips(tex, mips)) tex->status = TEX_LOADED; else @@ -2299,6 +2299,7 @@ static void Image_LoadTextureMips(void *ctx, void *data, size_t a, size_t b) BZ_Free(mips->extrafree); BZ_Free(mips); +/* if (!strncmp(tex->ident, "gfx/", 4)) { qpic_t *pic = W_SafeGetLumpName(tex->ident+4); @@ -2308,6 +2309,7 @@ static void Image_LoadTextureMips(void *ctx, void *data, size_t a, size_t b) tex->height = pic->height; } } +*/ } #ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 403ebd47..107f5451 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -2758,7 +2758,7 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_ { case MV_NONE: R_DrawTextField(r_refdef.grect.x, r_refdef.grect.y+y, r_refdef.grect.width, r_refdef.grect.height-y, - "arrows: pitch/rotate\n" + va("arrows: pitch/rotate\n" "w: zoom in\n" "s: zoom out\n" "m: mode\n" @@ -2767,6 +2767,7 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct menu_ "end: skin+=1\n" "pgup: frame+=1\n" "pgdn: frame-=1\n" + "mins: %g %g %g, maxs: %g %g %g\n", ent.model->mins[0], ent.model->mins[1], ent.model->mins[2], ent.model->maxs[0], ent.model->maxs[1], ent.model->maxs[2]) , CON_WHITEMASK, CPRINT_TALIGN|CPRINT_LALIGN, font_default, fs); break; case MV_BONES: diff --git a/engine/client/m_single.c b/engine/client/m_single.c index 66bda8eb..333816d9 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -70,7 +70,7 @@ void M_ScanSaves (void) memcpy(m_saves[i].map, line, 22); m_saves[i].map[22] = 0; memcpy(m_saves[i].kills, line+22, 39-22); - m_saves[i].kills[22] = 0; + m_saves[i].kills[39-22] = 0; Q_strncpyz(m_saves[i].time, line+39, sizeof(m_saves[i].time)); diff --git a/engine/client/merged.h b/engine/client/merged.h index 0a0e9100..8ebab723 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -164,7 +164,7 @@ char *Mod_GetBoneName(struct model_s *model, int bonenum); void Draw_FunString(float x, float y, const void *str); void Draw_AltFunString(float x, float y, const void *str); -void Draw_FunStringWidth(float x, float y, const void *str, int width, qboolean rightalign, qboolean highlight); +void Draw_FunStringWidth(float x, float y, const void *str, int width, int rightalign, qboolean highlight); extern int r_regsequence; diff --git a/engine/client/sbar.c b/engine/client/sbar.c index be5e990c..10fb598c 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -204,7 +204,7 @@ void Draw_AltFunString(float x, float y, const void *str) } //Draws a marked up string no wider than $width virtual pixels. -void Draw_FunStringWidth(float x, float y, const void *str, int width, qboolean rightalign, qboolean highlight) +void Draw_FunStringWidth(float x, float y, const void *str, int width, int rightalign, qboolean highlight) { conchar_t buffer[2048]; conchar_t *w; diff --git a/engine/client/snd_al.c b/engine/client/snd_al.c index 415e9207..d8c6ed1e 100644 --- a/engine/client/snd_al.c +++ b/engine/client/snd_al.c @@ -678,11 +678,16 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned } palSourcef(src, AL_GAIN, min(cvolume, 1)); //openal only supports a max volume of 1. anything above is an error and will be clamped. - if (chan->entnum == -1 || chan->entnum == cl.playerview[0].viewentity) + if ((chan->flags & CF_NOSPACIALISE) || chan->entnum == cl.playerview[0].viewentity || !chan->dist_mult) + { palSourcefv(src, AL_POSITION, vec3_origin); + palSourcefv(src, AL_VELOCITY, vec3_origin); + } else + { palSourcefv(src, AL_POSITION, chan->origin); - palSourcefv(src, AL_VELOCITY, vec3_origin); + palSourcefv(src, AL_VELOCITY, vec3_origin); //FIXME + } if (schanged) { @@ -697,7 +702,7 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned #endif palSourcei(src, AL_LOOPING, (chan->flags & CF_FORCELOOP)?AL_TRUE:AL_FALSE); - if (chan->entnum == -1 || chan->entnum == cl.playerview[0].viewentity) + if ((chan->flags & CF_NOSPACIALISE) || chan->entnum == cl.playerview[0].viewentity || !chan->dist_mult) { palSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE); // palSourcef(src, AL_ROLLOFF_FACTOR, 0.0f); diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index bbb96c44..c2719185 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -2814,6 +2814,11 @@ void S_UpdateAmbientSounds (soundcardinfo_t *sc) chan->rate = 1<pos = (int)(time * sc->sn.speed) * chan->rate; changed = true; + + chan->master_vol = bound(0, 1, 255); + chan->vol[0] = chan->vol[1] = chan->vol[2] = chan->vol[3] = chan->vol[4] = chan->vol[5] = chan->master_vol; + if (sc->ChannelUpdate) + sc->ChannelUpdate(sc, chan, changed); } } } @@ -2997,7 +3002,8 @@ static void S_UpdateCard(soundcardinfo_t *sc) for (i=0 ; itotal_chans; i++, ch++) if (ch->sfx && (ch->vol[0] || ch->vol[1]) ) { -// Con_Printf ("%i, %i %i %i %i %i %i %s\n", i, ch->vol[0], ch->vol[1], ch->vol[2], ch->vol[3], ch->vol[4], ch->vol[5], ch->sfx->name); + if (snd_show.ival > 1) + Con_Printf ("%i, %i %i %i %i %i %i %s\n", i, ch->vol[0], ch->vol[1], ch->vol[2], ch->vol[3], ch->vol[4], ch->vol[5], ch->sfx->name); total++; } diff --git a/engine/client/sound.h b/engine/client/sound.h index fa2bb3d0..6788f9a6 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -67,7 +67,7 @@ typedef struct sfx_s typedef struct sfxcache_s { usamplepos_t length; //sample count - unsigned int loopstart; //-1 or sample index to begin looping at once the sample ends + int loopstart; //-1 or sample index to begin looping at once the sample ends unsigned int speed; unsigned int width; unsigned int numchannels; diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index a00b4dd7..c23dd338 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -32,6 +32,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "pr_common.h" #include "fs.h" +//#define _MSC_SEH + //#define RESTARTTEST #ifdef MULTITHREAD @@ -3491,7 +3493,9 @@ qboolean Sys_DoInstall(void) GetClientRect(wnd, &ca); sh = GetSystemMetrics(SM_CYVSCROLL); - InitCommonControls(); + Sys_LoadLibrary("comctl32.dll", NULL); +// InitCommonControls(); + label = CreateWindow("STATIC","", WS_CHILD | WS_VISIBLE | SS_PATHELLIPSIS, sh, ((ca.bottom-ca.top-sh)/3), ca.right-ca.left-2*sh, sh, wnd, NULL, hInstance, NULL); progress = CreateWindowEx(0, PROGRESS_CLASS, NULL, WS_CHILD | WS_VISIBLE | PBS_SMOOTH, sh, ((ca.bottom-ca.top-sh)/3)*2, ca.right-ca.left-2*sh, sh, wnd, NULL, hInstance, NULL); @@ -3816,6 +3820,9 @@ static void Sys_MakeInstaller(const char *name) } #endif +#if defined(_MSC_VER) && defined(_AMD64_) +#pragma optimize( "", off) //64bit msvc sucks and falls over when trying to inline Host_Frame +#endif int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // MSG msg; @@ -3886,7 +3893,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin #ifdef CATCHCRASH LoadLibraryU ("DBGHELP"); //heap corruption can prevent loadlibrary from working properly, so do this in advance. -#ifdef _MSC_VER +#ifdef _MSC_SEH __try #else { @@ -4199,7 +4206,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin } } #ifdef CATCHCRASH -#ifdef _MSC_VER +#ifdef _MSC_SEH __except (CrashExceptionHandler(false, GetExceptionCode(), GetExceptionInformation())) { return 1; @@ -4210,6 +4217,9 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin /* return success of application */ return TRUE; } +#ifdef _MSC_VER +#pragma optimize( "", on) //revert back to default optimisations again. +#endif int __cdecl main(void) { diff --git a/engine/client/view.c b/engine/client/view.c index aec2e1ac..bd1e005b 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1882,7 +1882,7 @@ void R_DrawNameTags(void) isteam = !strcmp(cl.players[i].team, ourteam); if (!isteam) - if (!cl.spectator && !cls.demoplayback || !scr_autoid.ival) + if ((!cl.spectator && !cls.demoplayback) || !scr_autoid.ival) continue; //only show our team when playing, too cheaty otherwise. SCR_DrawAutoID(nametagorg[i], &cl.players[i], isteam); diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index d71483c3..068ee3f7 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -6801,9 +6801,6 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize) maxs[2] = LittleFloat(inbounds[i].bbmax[2]); AddPointToBounds(maxs, mod->mins, mod->maxs); } - //fixme: shouldn't really be needed for an animated model - for (i = 0; i < h->num_vertexes; i++) - AddPointToBounds(opos[i], mod->mins, mod->maxs); for (i = 0; i < h->num_meshes; i++) { @@ -6882,6 +6879,10 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize) IQM_ImportArrayF(buffer, &vnorm, (float*)onorm1, 3, h->num_vertexes, defaultcolour); IQM_ImportArrayF(buffer, &vpos, (float*)opos, sizeof(opos[0])/sizeof(float), h->num_vertexes, defaultvert); + //fixme: shouldn't really be needed for an animated model + for (i = 0; i < h->num_vertexes; i++) + AddPointToBounds(opos[i], mod->mins, mod->maxs); + if (vnorm.offset && vtang) { for (i = 0; i < h->num_vertexes; i++) diff --git a/engine/common/sys_win_threads.c b/engine/common/sys_win_threads.c index 55f26b1b..620c4337 100644 --- a/engine/common/sys_win_threads.c +++ b/engine/common/sys_win_threads.c @@ -74,6 +74,12 @@ typedef struct threadwrap_s char name[1]; } threadwrap_t; +typedef struct +{ + HANDLE handle; + DWORD threadid; +} threadctx_t; + // the thread call is wrapped so we don't need WINAPI everywhere unsigned int WINAPI threadwrapper(void *args) { @@ -104,42 +110,48 @@ unsigned int WINAPI threadwrapper(void *args) void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority, int stacksize) { + threadctx_t *ctx = (threadctx_t *)malloc(sizeof(*ctx)); threadwrap_t *tw = (threadwrap_t *)malloc(sizeof(threadwrap_t)+strlen(name)); - HANDLE handle; - unsigned int tid; - if (!tw) + if (!tw || !ctx) + { + free(tw); + free(ctx); return NULL; + } stacksize += 128; // wrapper overhead, also prevent default stack size tw->func = func; tw->args = args; strcpy(tw->name, name); #ifdef WIN32CRTDLL - handle = (HANDLE)CreateThread(NULL, stacksize, &threadwrapper, (void *)tw, 0, &tid); + ctx->handle = (HANDLE)CreateThread(NULL, stacksize, &threadwrapper, (void *)tw, 0, &ctx->threadid); #else - handle = (HANDLE)_beginthreadex(NULL, stacksize, &threadwrapper, (void *)tw, 0, &tid); + ctx->handle = (HANDLE)_beginthreadex(NULL, stacksize, &threadwrapper, (void *)tw, 0, &ctx->threadid); #endif - if (!handle) + if (!ctx->handle) { free(tw); + free(ctx); return NULL; } - - - return (void *)handle; + return (void *)ctx; } void Sys_DetachThread(void *thread) { - CloseHandle((HANDLE)thread); + threadctx_t *ctx = thread; + CloseHandle(ctx->handle); + free(ctx); } void Sys_WaitOnThread(void *thread) { - WaitForSingleObject((HANDLE)thread, INFINITE); - CloseHandle((HANDLE)thread); + threadctx_t *ctx = thread; + WaitForSingleObject(ctx->handle, INFINITE); + CloseHandle(ctx->handle); + free(ctx); } //used on fatal errors. @@ -160,7 +172,8 @@ qboolean Sys_IsMainThread(void) qboolean Sys_IsThread(void *thread) { - return GetThreadId(thread) == GetCurrentThreadId(); + threadctx_t *ctx = thread; + return ctx->threadid == GetCurrentThreadId(); } diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 51dae445..3c65af16 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -342,8 +342,8 @@ qboolean GL_LoadTextureMips(texid_t tex, struct pendingtextureinfo *mips) } } - tex->width = mips->mip[0].width; - tex->height = mips->mip[0].height; +// tex->width = mips->mip[0].width; +// tex->height = mips->mip[0].height; GL_Texturemode_Apply(targ, tex->flags); if (targ == GL_TEXTURE_3D) { diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index d147db1e..06d2dbc7 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -608,22 +608,34 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) Con_DPrintf("Anisotropic filter extension found (%dx max).\n",gl_config.ext_texture_filter_anisotropic); } - //FIXME: GL_ARB_texture_non_power_of_two is supposed to be mandatory in gl2+ and thus checking for it is redundant and not forwards-compatible - //geforcefx apparently software emulates it, so gl<3 is bad. - if (GL_CheckExtension("GL_ARB_texture_non_power_of_two")) - { + if (!gl_config.gles && gl_config.glversion >= 3) + { //GL_ARB_texture_non_power_of_two is supposed to be mandatory in gl2+ and thus checking for it is redundant and not forwards-compatible + //geforcefx apparently software emulates it, so only activate it unconditionally on gl3+ hardware. sh_config.texture_non_power_of_two = true; - //gles2 has limited npot as standard, which is sufficient to make the hud not look like poo. lets use it. - if ((gl_config.gles && gl_config.glversion >= 2) || sh_config.texture_non_power_of_two) - sh_config.texture_non_power_of_two_pic = true; + sh_config.texture_non_power_of_two_pic = true; } - else if (GL_CheckExtension("GL_OES_texture_npot")) - { + else if (GL_CheckExtension("GL_ARB_texture_non_power_of_two")) + { //gl1 devices might still support npot + sh_config.texture_non_power_of_two = true; + sh_config.texture_non_power_of_two_pic = true; + } + else if (gl_config.gles && GL_CheckExtension("GL_OES_texture_npot")) + { //gles devices might have full npot too, but with a different extension name. because consistancy is good... + sh_config.texture_non_power_of_two = true; + sh_config.texture_non_power_of_two_pic = true; + } + else if (gl_config.gles && gl_config.glversion >= 2) + { //gles2 has npot (clamp + no mips) support as base. + sh_config.texture_non_power_of_two = false; + sh_config.texture_non_power_of_two_pic = true; + } + else if (gl_config.gles && GL_CheckExtension("GL_APPLE_texture_2D_limited_npot")) + { //gles1 MIGHT have SOME npot support. sh_config.texture_non_power_of_two = false; sh_config.texture_non_power_of_two_pic = true; } else - { + { //really old hardware/drivers with no npot support at all. sh_config.texture_non_power_of_two = false; sh_config.texture_non_power_of_two_pic = false; } diff --git a/engine/qclib/progsint.h b/engine/qclib/progsint.h index 1114e432..6dc397c3 100644 --- a/engine/qclib/progsint.h +++ b/engine/qclib/progsint.h @@ -173,7 +173,7 @@ typedef struct int targetflags; //weather we need to mark the progs as a newer version char *name; char *opname; - int priority; //FIXME: priority should be done differently... + int priority_; //FIXME: priority should be done differently... enum {ASSOC_LEFT, ASSOC_RIGHT, ASSOC_RIGHT_RESULT} associative; struct QCC_type_s **type_a, **type_b, **type_c; @@ -556,4 +556,5 @@ void PR_CloseJit(struct jitstate *jit); char *QCC_COM_Parse (const char *data); extern char qcc_token[1024]; +extern char *basictypenames[]; #endif diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index ddbe5fd4..4eee50cc 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -454,6 +454,7 @@ const extern unsigned int type_size[]; //extern QCC_def_t *def_for_type[9]; extern QCC_type_t *type_void, *type_string, *type_float, *type_vector, *type_entity, *type_field, *type_function, *type_floatfunction, *type_pointer, *type_floatpointer, *type_intpointer, *type_integer, *type_variant, *type_floatfield; +extern char *basictypenames[]; struct QCC_function_s { @@ -574,7 +575,7 @@ extern pbool keywords_coexist; extern pbool output_parms; extern pbool autoprototype, autoprototyped, parseonly; extern pbool pr_subscopedlocals; -extern pbool flag_nullemptystr, flag_ifstring, flag_iffloat, flag_ifvector, flag_vectorlogic; +extern pbool flag_nullemptystr, flag_ifstring, flag_brokenifstring, flag_iffloat, flag_ifvector, flag_vectorlogic; extern pbool flag_acc; extern pbool flag_caseinsensitive; extern pbool flag_laxcasts; diff --git a/engine/qclib/qcc_cmdlib.c b/engine/qclib/qcc_cmdlib.c index 097c724b..c7bf60a8 100644 --- a/engine/qclib/qcc_cmdlib.c +++ b/engine/qclib/qcc_cmdlib.c @@ -33,6 +33,23 @@ const unsigned int type_size[12] = {1, //void 0 //ev_union. variable sized. }; + +char *basictypenames[] = { + "void", + "string", + "float", + "vector", + "entity", + "field", + "function", + "pointer", + "integer", + "variant", + "struct", + "union", + "accessor" +}; + /* ============================================================================ diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 368b6ccc..876fb4f9 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -87,6 +87,7 @@ pbool autoprototyped; //previously autoprototyped. no longer allowed to enable pbool parseonly; //parse defs and stuff, but don't bother compiling any actual code. pbool pr_subscopedlocals; //causes locals to be valid ONLY within their statement block. (they simply can't be referenced by name outside of it) pbool flag_nullemptystr; //null immediates are 0, not 1. +pbool flag_brokenifstring; //break strings even more pbool flag_ifstring; //makes if (blah) equivelent to if (blah != "") which resolves some issues in multiprogs situations. pbool flag_iffloat; //use an op_if_f instruction instead of op_if so if(-0) evaluates to false. pbool flag_ifvector; //use an op_not_v instruction instead of testing only _x. @@ -456,7 +457,7 @@ QCC_opcode_t pr_opcodes[] = {7, "!", "NOT_I", -1, ASSOC_LEFT, &type_integer, &type_void, &type_integer}, - {7, "/", "DIV_VF", 3, ASSOC_LEFT, &type_vector, &type_float, &type_float}, + {7, "/", "DIV_VF", 3, ASSOC_LEFT, &type_vector, &type_float, &type_vector}, {7, "^", "BITXOR_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, {7, ">>", "RSHIFT_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, @@ -707,12 +708,22 @@ pbool OpAssignsToB(unsigned int op) */ #undef ASSOC_RIGHT_RESULT -#define TOP_PRIORITY 7 -#define FUNC_PRIORITY 1 -#define UNARY_PRIORITY 1 -#define NOT_PRIORITY 5 -//conditional and/or -#define CONDITION_PRIORITY 7 +#define FUNC_PRIORITY 1 +#define UNARY_PRIORITY 1 //~ ! +#define NOT_PRIORITY 5 //UNARY_PRIORITY +#define MULDIV_PRIORITY 3 //* / % +#define ADDSUB_PRIORITY 4 //+ - +#define BITSHIFT_PRIORITY 3 //<< >> +#define COMPARISON_PRIORITY 5 //< <= > >= +#define EQUALITY_PRIORITY 5 //== != +#define BITAND_PRIORITY 3 //& +#define BITXOR_PRIORITY 3 //^ +#define BITOR_PRIORITY 3 //| +#define LOGICAND_PRIORITY 7 //&& +#define LOGICOR_PRIORITY 7 //|| +#define TERNARY_PRIORITY 6 //?: +#define ASSIGN_PRIORITY 6 //WRONG compared to C +#define TOP_PRIORITY 7 QCC_opcode_t *opcodes_store[] = { @@ -2037,7 +2048,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_ QCC_UnFreeTemp(var_b); } - if (op->priority != -1 && op->priority != CONDITION_PRIORITY) +/* if (op->priority != -1 && op->priority != CONDITION_PRIORITY) { if (op->associative!=ASSOC_LEFT) { @@ -2052,7 +2063,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_ var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type, false); } } - +*/ //maths operators if (opt_constantarithmatic || !pr_scope) { @@ -3007,6 +3018,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_ //v/f === v*(1/f) op = &pr_opcodes[OP_MUL_VF]; var_b = QCC_PR_Statement(&pr_opcodes[OP_DIV_F], QCC_MakeFloatConst(1), var_b, NULL); + var_b.sym->referenced = true; break; case OP_CONV_ITOF: @@ -3614,9 +3626,9 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_ case OP_AND_IF: case OP_AND_ANY: if (var_a.cast->type == ev_vector && flag_vectorlogic) //we can do a dot-product to test if a vector has a value, instead of a double-not - var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_V], var_a, var_a, NULL, flags&STFL_PRESERVEA); + var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_V], var_a, var_a, NULL, STFL_PRESERVEA | (flags&STFL_PRESERVEA?STFL_PRESERVEB:0)); if (var_b.cast->type == ev_vector && flag_vectorlogic) - var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_V], var_b, var_b, NULL, flags&STFL_PRESERVEB); + var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_V], var_b, var_b, NULL, STFL_PRESERVEA | (flags&STFL_PRESERVEB?STFL_PRESERVEB:0)); if (((var_a.cast->size != 1 && flag_vectorlogic) || (var_a.cast->type == ev_string && flag_ifstring)) && ((var_b.cast->size != 1 && flag_vectorlogic) || (var_b.cast->type == ev_string && flag_ifstring))) { //just 3 extra instructions instead of 4. @@ -3643,9 +3655,9 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_ case OP_OR_IF: case OP_OR_ANY: if (var_a.cast->type == ev_vector && flag_vectorlogic) //we can do a dot-product to test if a vector has a value, instead of a double-not - var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_V], var_a, var_a, NULL, flags&STFL_PRESERVEA); + var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_V], var_a, var_a, NULL, STFL_PRESERVEA | (flags&STFL_PRESERVEA?STFL_PRESERVEB:0)); if (var_b.cast->type == ev_vector && flag_vectorlogic) - var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_V], var_b, var_b, NULL, flags&STFL_PRESERVEB); + var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_V], var_b, var_b, NULL, STFL_PRESERVEA | (flags&STFL_PRESERVEB?STFL_PRESERVEB:0)); if (((var_a.cast->size != 1 && flag_vectorlogic) || (var_a.cast->type == ev_string && flag_ifstring)) && ((var_b.cast->size != 1 && flag_vectorlogic) || (var_b.cast->type == ev_string && flag_ifstring))) { //just 3 extra instructions instead of 4. @@ -5664,22 +5676,6 @@ QCC_type_t *QCC_PointerTypeTo(QCC_type_t *type) return newtype; } -char *basictypenames[] = { - "void", - "string", - "float", - "vector", - "entity", - "field", - "function", - "pointer", - "integer", - "variant", - "struct", - "union", - "accessor" -}; - QCC_type_t **basictypes[] = { &type_void, @@ -6695,7 +6691,7 @@ QCC_sref_t QCC_PR_GenerateLogicalNot(QCC_sref_t e, const char *errormessage) if (t == ev_float) return QCC_PR_Statement (&pr_opcodes[OP_NOT_F], e, nullsref, NULL); else if (t == ev_string) - return QCC_PR_Statement (&pr_opcodes[OP_NOT_S], e, nullsref, NULL); + return QCC_PR_Statement (&pr_opcodes[flag_brokenifstring?OP_NOT_ENT:OP_NOT_S], e, nullsref, NULL); else if (t == ev_entity) return QCC_PR_Statement (&pr_opcodes[OP_NOT_ENT], e, nullsref, NULL); else if (t == ev_vector) @@ -8042,9 +8038,9 @@ QCC_opcode_t *QCC_PR_ChooseOpcode(QCC_sref_t lhs, QCC_sref_t rhs, QCC_opcode_t * } if (bestop == NULL) { - if (oldop->priority == CONDITION_PRIORITY) - op = oldop; - else +// if (oldop->priority == CONDITION_PRIORITY) +// op = oldop; +// else { op = oldop; QCC_PR_ParseWarning(flag_laxcasts?WARN_LAXCAST:ERR_TYPEMISMATCH, "type mismatch for %s (%s and %s)", oldop->name, lhs.cast->name, rhs.cast->name); @@ -8110,7 +8106,7 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags) lhsd = QCC_PR_ParseArrayPointer(lhsd, true, true); lhsr = QCC_DefToRef(retbuf, lhsd); } - if (priority == FUNC_PRIORITY && QCC_PR_CheckToken ("?")) + if (priority == TERNARY_PRIORITY && QCC_PR_CheckToken ("?")) { //if we have no int types, force all ints to floats here, just to ensure that we don't end up with non-constant ints that we then can't cope with. @@ -8128,7 +8124,7 @@ QCC_ref_t *QCC_PR_RefExpression (QCC_ref_t *retbuf, int priority, int exprflags) { fromj = QCC_Generate_OP_IFNOT(QCC_RefToDef(lhsr, true), false); - val = QCC_PR_Expression(TOP_PRIORITY, EXPR_DISALLOW_COMMA); + val = QCC_PR_Expression(TOP_PRIORITY, 0); if (val.cast->type == ev_integer && !QCC_OPCodeValid(&pr_opcodes[OP_STORE_I])) val = QCC_SupplyConversion(val, ev_float, true); r = QCC_GetTemp(val.cast); @@ -9748,7 +9744,7 @@ void QCC_PR_ParseAsm(void) if (!STRCMP(pr_token, pr_opcodes[op].opname)) { QCC_PR_Lex(); - if (pr_opcodes[op].priority==-1 && pr_opcodes[op].associative!=ASSOC_LEFT) + if (/*pr_opcodes[op].priority==-1 &&*/ pr_opcodes[op].associative!=ASSOC_LEFT) { if (pr_opcodes[op].type_a==NULL) { diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index 559e470b..a0bab919 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -454,6 +454,83 @@ static void QCC_PR_SkipToEndOfLine(pbool errorifnonwhite) } } } + +//if hadtrue, then we allow elses, otherwise we skip them. +pbool QCC_PR_FalsePreProcessorIf(pbool hadtrue, int originalline) +{ + int eval; + int level = 1; + while (1) + { + while(*pr_file_p && (*pr_file_p==' ' || *pr_file_p == '\t')) + pr_file_p++; + + if (!*pr_file_p) + { + pr_source_line = originalline; + QCC_PR_ParseError (ERR_NOENDIF, "#if with no endif"); + } + + if (*pr_file_p == '#') + { + pr_file_p++; + while(*pr_file_p==' ' || *pr_file_p == '\t') + pr_file_p++; + if (!strncmp(pr_file_p, "endif", 5)) + level--; + if (!strncmp(pr_file_p, "if", 2)) + level++; + if (!hadtrue && !strncmp(pr_file_p, "else", 4) && level == 1) + { + pr_file_p+=4; + QCC_PR_SkipToEndOfLine(true); + return true; + } + if (!hadtrue && !strncmp(pr_file_p, "elif", 4) && level == 1) + { +// QCC_PR_ParseError(ERR_UNKNOWNPUCTUATION, "#elif not supported\n"); + + pr_file_p += 4; + if (!strncmp(pr_file_p, "def", 3)) + { + eval = 1; + pr_file_p += 3; + } + else if (!strncmp(pr_file_p, "ndef", 4)) + { + eval = 0; + pr_file_p += 4; + } + else + eval = 2; + if (*pr_file_p != ' ' && *pr_file_p != '\t') + QCC_PR_ParseError(ERR_UNKNOWNPUCTUATION, "malformed #elif\n"); + if (eval == 2) + eval = ParsePrecompilerIf(PPI_TOPLEVEL); + else + { + QCC_PR_SimpleGetToken (); + if (eval) + eval = !!QCC_PR_CheckCompConstDefined(pr_token); + else + eval = !QCC_PR_CheckCompConstDefined(pr_token); + } + if (eval) + { + QCC_PR_SkipToEndOfLine(true); + return true; + } + } + } + + QCC_PR_SkipToEndOfLine(false); + + if (level <= 0) + return false; + pr_file_p++; //next line + pr_source_line++; + } +} /* ============== QCC_PR_Precompiler @@ -467,7 +544,6 @@ pbool QCC_PR_Precompiler(void) int ifmode; int a; static int ifs = 0; - int level; //#if level pbool eval = false; if (*pr_file_p == '#') @@ -551,96 +627,29 @@ pbool QCC_PR_Precompiler(void) } QCC_PR_SkipToEndOfLine(true); - level = 1; if (eval) ifs+=1; else - { - while (1) - { - while(*pr_file_p && (*pr_file_p==' ' || *pr_file_p == '\t')) - pr_file_p++; - - if (!*pr_file_p) - { - pr_source_line = originalline; - QCC_PR_ParseError (ERR_NOENDIF, "#if with no endif"); - } - - if (*pr_file_p == '#') - { - pr_file_p++; - while(*pr_file_p==' ' || *pr_file_p == '\t') - pr_file_p++; - if (!strncmp(pr_file_p, "endif", 5)) - level--; - if (!strncmp(pr_file_p, "if", 2)) - level++; - if (!strncmp(pr_file_p, "else", 4) && level == 1) - { - ifs+=1; - pr_file_p+=4; - QCC_PR_SkipToEndOfLine(true); - break; - } - } - - QCC_PR_SkipToEndOfLine(false); - - if (level <= 0) - break; - pr_file_p++; //next line - pr_source_line++; - } - } + ifs += QCC_PR_FalsePreProcessorIf(false, originalline); } } - else if (!strncmp(directive, "else", 4)) + else if (!strncmp(directive, "else", 4) || !strncmp(directive, "elif", 4)) { int originalline = pr_source_line; + if (!ifs) + QCC_PR_ParseError(ERR_UNKNOWNPUCTUATION, "#else outside of #if\n"); + ifs -= 1; - level = 1; pr_file_p = directive+4; - QCC_PR_SkipToEndOfLine(true); - while (1) - { - while(*pr_file_p && (*pr_file_p==' ' || *pr_file_p == '\t')) - pr_file_p++; - - if (!*pr_file_p) - { - pr_source_line = originalline; - QCC_PR_ParseError(ERR_NOENDIF, "#if with no endif"); - } - - if (*pr_file_p == '#') - { - pr_file_p++; - while(*pr_file_p==' ' || *pr_file_p == '\t') - pr_file_p++; - - if (!strncmp(pr_file_p, "endif", 5)) - level--; - if (!strncmp(pr_file_p, "if", 2)) - level++; - if (!strncmp(pr_file_p, "else", 4) && level == 1) - { - ifs+=1; - pr_file_p+=4; - QCC_PR_SkipToEndOfLine(true); - break; - } - } - + if (!strncmp(directive, "elif", 4)) QCC_PR_SkipToEndOfLine(false); - if (level <= 0) - break; - pr_file_p++; //go off the end - pr_source_line++; - } + else + QCC_PR_SkipToEndOfLine(true); + + ifs += QCC_PR_FalsePreProcessorIf(true, originalline); } else if (!strncmp(directive, "endif", 5)) { diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 28f045b1..c297e004 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -3261,7 +3261,7 @@ void QCC_PR_CommandLinePrecompilerOptions (void) else if (!stricmp(arg, "false-empty-strings")) flag_ifstring = state; else if (!stricmp(arg, "true-empty-strings")) - flag_ifstring = flag_nullemptystr = state; + flag_brokenifstring = state; else QCC_PR_Warning(0, NULL, WARN_BADPARAMS, "Unrecognised flag parameter (%s)", myargv[i]); } diff --git a/engine/qclib/qcctui.c b/engine/qclib/qcctui.c index ad84ac2f..b4c31211 100644 --- a/engine/qclib/qcctui.c +++ b/engine/qclib/qcctui.c @@ -108,7 +108,7 @@ int main (int argc, char **argv) funcs.funcs.parms->WriteFile = QCC_WriteFile; funcs.funcs.parms->Printf = logprintf; funcs.funcs.parms->Sys_Error = Sys_Error; - logfile = fopen("fteqcc.log", "wt"); + logfile = fopen("fteqcc.log", "at"); fputs("Args:", logfile); for (i = 0; i < argc; i++) { diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index b8199f0a..0b298031 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -255,11 +255,15 @@ void SV_Shutdown (void) NET_Shutdown (); +#ifdef PLUGINS Plug_Shutdown(true); +#endif Mod_Shutdown(true); COM_DestroyWorkerThread(); FS_Shutdown(); +#ifdef PLUGINS Plug_Shutdown(false); +#endif Cvar_Shutdown(); Cmd_Shutdown(); diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 2fccf913..081b9626 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -4731,9 +4731,12 @@ void Cmd_Join_f (void) // call the prog function for removing a client // this will set the body to a dead frame, among other things pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); +#ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) Q1QVM_DropClient(host_client); - else if (SpectatorDisconnect) + else +#endif + if (SpectatorDisconnect) PR_ExecuteProgram (svprogfuncs, SpectatorDisconnect); sv.spawned_observer_slots--; @@ -4746,9 +4749,12 @@ void Cmd_Join_f (void) // FIXME, bump the client's userid? // call the progs to get default spawn parms for the new client +#ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) Q1QVM_SetNewParms(); - else if (pr_global_ptrs->SetNewParms) + else +#endif + if (pr_global_ptrs->SetNewParms) PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); for (i=0 ; ispawn_parms[i] = 0; } +#ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) Q1QVM_ClientConnect(host_client); else +#endif { // call the spawn function pr_global_struct->time = sv.world.physicstime; @@ -4861,9 +4869,11 @@ void Cmd_Observe_f (void) // call the prog function for removing a client // this will set the body to a dead frame, among other things +#ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) Q1QVM_DropClient(host_client); else +#endif { pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); PR_ExecuteProgram (svprogfuncs, pr_global_struct->ClientDisconnect); @@ -4879,9 +4889,12 @@ void Cmd_Observe_f (void) // FIXME, bump the client's userid? // call the progs to get default spawn parms for the new client +#ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) Q1QVM_SetNewParms(); - else if (pr_global_ptrs->SetNewParms) + else +#endif + if (pr_global_ptrs->SetNewParms) PR_ExecuteProgram (svprogfuncs, pr_global_struct->SetNewParms); for (i=0 ; i