From 591ee6b490a0ad40c5d28998b6c836f11139f73e Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 15 May 2015 16:04:23 +0300 Subject: [PATCH 1/3] More SSE optimizations. --- rehlds/engine/common.cpp | 17 +++-- rehlds/engine/mathlib.cpp | 115 ++++++++++++++++++++++---------- rehlds/engine/mathlib_e.h | 3 +- rehlds/engine/model.cpp | 16 ++--- rehlds/engine/pmovetst.cpp | 75 +++++++++------------ rehlds/engine/pr_cmds.cpp | 28 ++++---- rehlds/engine/sv_phys.cpp | 46 ++++++------- rehlds/public/rehlds/osconfig.h | 2 + 8 files changed, 174 insertions(+), 128 deletions(-) diff --git a/rehlds/engine/common.cpp b/rehlds/engine/common.cpp index 6ab96b5..66b1ad0 100644 --- a/rehlds/engine/common.cpp +++ b/rehlds/engine/common.cpp @@ -263,14 +263,15 @@ float (*LittleFloat)(float l); int LongSwap(int l) { - byte b1, b2, b3, b4; + /*byte b1, b2, b3, b4; b1 = l & 0xFF; b2 = (l >> 8) & 0xFF; b3 = (l >> 16) & 0xFF; b4 = (l >> 24) & 0xFF; - return ((int)b1 << 24) + ((int)b2 << 16) + ((int)b3 << 8) + b4; + return ((int)b1 << 24) + ((int)b2 << 16) + ((int)b3 << 8) + b4;*/ + return _byteswap_ulong(l); } int LongNoSwap(int l) @@ -280,12 +281,16 @@ int LongNoSwap(int l) short ShortSwap(short l) { +#ifdef _WIN32 + return _byteswap_ushort(l); // xchg +#else byte b1, b2; b1 = l & 0xFF; b2 = (l >> 8) & 0xFF; return (b1 << 8) + b2; +#endif } short ShortNoSwap(short l) @@ -295,7 +300,7 @@ short ShortNoSwap(short l) float FloatSwap(float f) { - union + /*union { float f; byte b[4]; @@ -307,7 +312,9 @@ float FloatSwap(float f) dat2.b[2] = dat1.b[1]; dat2.b[3] = dat1.b[0]; - return dat2.f; + return dat2.f;*/ + unsigned long u = _byteswap_ulong(*(unsigned long *)&f); + return *(float *)&u; } float FloatNoSwap(float f) @@ -443,7 +450,7 @@ void MSG_WriteUsercmd(sizebuf_t *buf, usercmd_t *to, usercmd_t *from) { delta_t **ppdesc; - ppdesc = (delta_t **)DELTA_LookupRegistration("usercmd_t"); + ppdesc = DELTA_LookupRegistration("usercmd_t"); MSG_StartBitWriting(buf); DELTA_WriteDelta((byte *)from, (byte *)to, 1, *ppdesc, 0); MSG_EndBitWriting(buf); diff --git a/rehlds/engine/mathlib.cpp b/rehlds/engine/mathlib.cpp index 1347fd7..4e986be 100644 --- a/rehlds/engine/mathlib.cpp +++ b/rehlds/engine/mathlib.cpp @@ -37,6 +37,24 @@ vec3_t vec3_origin; //short int old_cw; //DLONG dlong; +// aligned vec4_t +typedef ALIGN16 vec4_t avec4_t; + +// conversion multiplier +const avec4_t deg2rad = +{ + M_PI / 180.f, + M_PI / 180.f, + M_PI / 180.f, + M_PI / 180.f +}; + +// save 4d xmm to 3d vector. we can't optimize many simple vector3 functions because saving back to 3d is slow. +void xmm2vec(vec_t *v, const __m128 m) +{ + _mm_store_ss(v, m); + _mm_storel_pi((__m64*)(v + 1), _mm_shuffle_ps(m, m, _MM_SHUFFLE(3, 2, 2, 1))); +} /* <46ebf> ../engine/mathlib.c:14 */ float anglemod(float a) @@ -126,19 +144,6 @@ NOBODY int InvertMatrix(const float *m, float *out); // float *r3; // 161 //} -#ifdef REHLDS_FIXES -void SinCos(float radians, float *sine, float *cosine) -{ - __asm - { - fld dword ptr [radians]; - fsincos; - fstp dword ptr [cosine]; - fstp dword ptr [sine]; - } -} -#endif // REHLDS_FIXES - /* <47067> ../engine/mathlib.c:267 */ void AngleVectors(const vec_t *angles, vec_t *forward, vec_t *right, vec_t *up) { @@ -149,9 +154,16 @@ void AngleVectors(const vec_t *angles, vec_t *forward, vec_t *right, vec_t *up) #endif // SWDS #ifdef REHLDS_FIXES - SinCos(DEG2RAD(angles[YAW]), &sy, &cy); - SinCos(DEG2RAD(angles[PITCH]), &sp, &cp); - SinCos(DEG2RAD(angles[ROLL]), &sr, &cr); + // convert to radians + avec4_t rad_angles; + _mm_store_ps(rad_angles, _mm_mul_ps(_mm_loadu_ps(angles), _mm_load_ps(deg2rad))); + + sy = sin(rad_angles[YAW]); + cy = cos(rad_angles[YAW]); + sp = sin(rad_angles[PITCH]); + cp = cos(rad_angles[PITCH]); + sr = sin(rad_angles[ROLL]); + cr = cos(rad_angles[ROLL]); #else float angle; angle = (float)(angles[YAW] * (M_PI * 2 / 360)); @@ -191,9 +203,16 @@ void AngleVectorsTranspose(const vec_t *angles, vec_t *forward, vec_t *right, ve float sr, sp, sy, cr, cp, cy; #ifdef REHLDS_FIXES - SinCos(DEG2RAD(angles[YAW]), &sy, &cy); - SinCos(DEG2RAD(angles[PITCH]), &sp, &cp); - SinCos(DEG2RAD(angles[ROLL]), &sr, &cr); + // convert to radians + avec4_t rad_angles; + _mm_store_ps(rad_angles, _mm_mul_ps(_mm_loadu_ps(angles), _mm_load_ps(deg2rad))); + + sy = sin(rad_angles[YAW]); + cy = cos(rad_angles[YAW]); + sp = sin(rad_angles[PITCH]); + cp = cos(rad_angles[PITCH]); + sr = sin(rad_angles[ROLL]); + cr = cos(rad_angles[ROLL]); #else float angle; angle = (float)(angles[YAW] * (M_PI * 2 / 360)); @@ -233,9 +252,16 @@ void AngleMatrix(const vec_t *angles, float(*matrix)[4]) float sr, sp, sy, cr, cp, cy; #ifdef REHLDS_FIXES - SinCos(DEG2RAD(angles[ROLL]), &sy, &cy); - SinCos(DEG2RAD(angles[YAW]), &sp, &cp); - SinCos(DEG2RAD(angles[PITCH]), &sr, &cr); + // convert to radians + avec4_t rad_angles; + _mm_store_ps(rad_angles, _mm_mul_ps(_mm_loadu_ps(angles), _mm_load_ps(deg2rad))); + + sy = sin(rad_angles[ROLL]); + cy = cos(rad_angles[ROLL]); + sp = sin(rad_angles[YAW]); + cp = cos(rad_angles[YAW]); + sr = sin(rad_angles[PITCH]); + cr = cos(rad_angles[PITCH]); #else float angle; angle = (float)(angles[ROLL] * (M_PI * 2 / 360)); @@ -321,11 +347,11 @@ int VectorCompare(const vec_t *v1, const vec_t *v2) } /* <47524> ../engine/mathlib.c:476 */ -void VectorMA(const vec_t *veca, float scale, const vec_t *vecb, vec_t *vecc) +void VectorMA(const vec_t *veca, float scale, const vec_t *vecm, vec_t *out) { - vecc[0] = scale * vecb[0] + veca[0]; - vecc[1] = scale * vecb[1] + veca[1]; - vecc[2] = scale * vecb[2] + veca[2]; + out[0] = scale * vecm[0] + veca[0]; + out[1] = scale * vecm[1] + veca[1]; + out[2] = scale * vecm[2] + veca[2]; } #ifndef REHLDS_FIXES @@ -337,7 +363,6 @@ long double _DotProduct(const vec_t *v1, const vec_t *v2) #else // REHLDS_FIXES float _DotProduct(const vec_t *v1, const vec_t *v2) { -#ifdef REHLDS_FIXES // _mm_loadu_ps - load xmm from unaligned address // _mm_cvtss_f32 - return low float value of xmm // _mm_dp_ps - dot product @@ -345,7 +370,6 @@ float _DotProduct(const vec_t *v1, const vec_t *v2) // dpps isn't binary compatible with separate sse2 instructions (max difference is about 0.0002f, but usually < 0.00001f) if (cpuinfo.sse4_1) return _mm_cvtss_f32(_mm_dp_ps(_mm_loadu_ps(v1), _mm_loadu_ps(v2), 0x71)); -#endif // REHLDS_FIXES return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; } @@ -372,9 +396,18 @@ NOBODY void _VectorCopy(vec_t *in, vec_t *out); /* <47679> ../engine/mathlib.c:510 */ void CrossProduct(const vec_t *v1, const vec_t *v2, vec_t *cross) { +#ifdef REHLDS_FIXES + __m128 a = _mm_loadu_ps(v1), b = _mm_loadu_ps(v2); + __m128 m = _mm_sub_ps( _mm_mul_ps(b, _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1))), + _mm_mul_ps(a, _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1))) + ); + + xmm2vec(cross, _mm_shuffle_ps(m, m, _MM_SHUFFLE(3, 0, 2, 1))); +#else // REHLDS_FIXES cross[0] = v2[2] * v1[1] - v1[2] * v2[1]; cross[1] = v1[2] * v2[0] - v1[0] * v2[2]; cross[2] = v1[0] * v2[1] - v2[0] * v1[1]; +#endif // REHLDS_FIXES } /* <476d8> ../engine/mathlib.c:519 */ @@ -383,9 +416,7 @@ float Length(const vec_t *v) #ifdef REHLDS_FIXES // based on dot product if (cpuinfo.sse4_1) - { - return _mm_cvtss_f32(_mm_sqrt_ps(_mm_dp_ps(_mm_loadu_ps(v), _mm_loadu_ps(v), 0x71))); - } + return _mm_cvtss_f32(_mm_sqrt_ss(_mm_dp_ps(_mm_loadu_ps(v), _mm_loadu_ps(v), 0x71))); #endif // REHLDS_FIXES float length; @@ -398,6 +429,17 @@ float Length(const vec_t *v) return sqrt(length); } +float Length2D(const vec_t *v) +{ +#ifdef REHLDS_FIXES + // based on dot product + if (cpuinfo.sse4_1) + return _mm_cvtss_f32(_mm_sqrt_ss(_mm_dp_ps(_mm_loadu_ps(v), _mm_loadu_ps(v), 0x31))); // 0b00110001 +#endif // REHLDS_FIXES + + return sqrt(v[0] * v[0] + v[1] * v[1]); +} + /* <47722> ../engine/mathlib.c:532 */ float VectorNormalize(vec3_t v) { @@ -457,7 +499,7 @@ NOBODY void VectorMatrix(vec_t *forward, vec_t *right, vec_t *up); /* <4794e> ../engine/mathlib.c:597 */ void VectorAngles(const vec_t *forward, vec_t *angles) { - float tmp, yaw, pitch; + float length, yaw, pitch; if (forward[1] == 0 && forward[0] == 0) { @@ -473,8 +515,13 @@ void VectorAngles(const vec_t *forward, vec_t *angles) if (yaw < 0) yaw += 360; - tmp = sqrt((double)(forward[0] * forward[0] + forward[1] * forward[1])); - pitch = (atan2((double)forward[2], (double)tmp) * 180.0 / M_PI); +#ifdef REHLDS_FIXES + length = Length2D(forward); +#else // REHLDS_FIXES + length = sqrt((double)(forward[0] * forward[0] + forward[1] * forward[1])); +#endif // REHLDS_FIXES + + pitch = atan2((double)forward[2], (double)length) * 180.0 / M_PI; if (pitch < 0) pitch += 360; } diff --git a/rehlds/engine/mathlib_e.h b/rehlds/engine/mathlib_e.h index 2495c2f..de06db7 100644 --- a/rehlds/engine/mathlib_e.h +++ b/rehlds/engine/mathlib_e.h @@ -70,7 +70,7 @@ NOBODY void NormalizeAngles(float *angles); NOBODY void InterpolateAngles(float *start, float *end, float *output, float frac); void VectorTransform(const vec_t *in1, float *in2, vec_t *out); int VectorCompare(const vec_t *v1, const vec_t *v2); -void VectorMA(const vec_t *veca, float scale, const vec_t *vecb, vec_t *vecc); +void VectorMA(const vec_t *veca, float scale, const vec_t *vecm, vec_t *out); #ifdef REHLDS_FIXES float _DotProduct(const vec_t *v1, const vec_t *v2); // with sse support #else // REHLDS_FIXES @@ -81,6 +81,7 @@ void _VectorAdd(vec_t *veca, vec_t *vecb, vec_t *out); NOBODY void _VectorCopy(vec_t *in, vec_t *out); void CrossProduct(const vec_t *v1, const vec_t *v2, vec_t *cross); float Length(const vec_t *v); +float Length2D(const vec_t *v); float VectorNormalize(vec_t *v); NOBODY void VectorInverse(vec_t *v); void VectorScale(const vec_t *in, float scale, vec_t *out); diff --git a/rehlds/engine/model.cpp b/rehlds/engine/model.cpp index a6c27e5..542fac4 100644 --- a/rehlds/engine/model.cpp +++ b/rehlds/engine/model.cpp @@ -99,7 +99,7 @@ mleaf_t *Mod_PointInLeaf(vec_t *p, model_t *model) { plane = node->plane; if (plane->type >= 3u) - d = plane->normal[2] * p[2] + plane->normal[1] * p[1] + plane->normal[0] * p[0] - plane->dist; + d = _DotProduct(plane->normal, p) - plane->dist; else d = p[plane->type] - plane->dist; @@ -258,7 +258,7 @@ qboolean IsCZPlayerModel(uint32 crc, const char * filename) model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean trackCRC) { unsigned char *buf; - char tmpName[260]; + char tmpName[MAX_PATH]; int length; CRC32_t currentCRC; @@ -282,11 +282,11 @@ model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean trackCRC) while (*(p++) == '/') ; - strncpy(tmpName, p, 259); - tmpName[259] = 0; + strncpy(tmpName, p, sizeof(tmpName) - 1); + tmpName[sizeof(tmpName) - 1] = '\0'; - strncpy(mod->name, tmpName, 63); - mod->name[63] = 0; + strncpy(mod->name, tmpName, sizeof(mod->name) - 1); + mod->name[sizeof(mod->name) - 1] = '\0'; } buf = COM_LoadFileForMe(mod->name, &length); @@ -383,7 +383,7 @@ void Mod_AdInit(void) { int i; char *s; - static char filename[260]; + static char filename[MAX_PATH]; tested = 1; i = COM_CheckParm("-ad"); @@ -392,7 +392,7 @@ void Mod_AdInit(void) s = com_argv[i + 1]; if (s && *s) { - _snprintf(filename, 0x104u, "%s", s); + _snprintf(filename, MAX_PATH, "%s", s); if (FS_FileSize(filename) > 0) { Sys_Error("Mod_Init(): reverse me"); diff --git a/rehlds/engine/pmovetst.cpp b/rehlds/engine/pmovetst.cpp index 59c1df6..26ee92e 100644 --- a/rehlds/engine/pmovetst.cpp +++ b/rehlds/engine/pmovetst.cpp @@ -50,10 +50,10 @@ float PM_TraceModel(physent_t *pEnt, vec_t *start, vec_t *end, trace_t *trace) pmove->usehull = 2; pHull = PM_HullForBsp(pEnt, offset); pmove->usehull = saveHull; - start_l[0] = *start - offset[0]; + start_l[0] = start[0] - offset[0]; start_l[1] = start[1] - offset[1]; start_l[2] = start[2] - offset[2]; - end_l[0] = *end - offset[0]; + end_l[0] = end[0] - offset[0]; end_l[1] = end[1] - offset[1]; end_l[2] = end[2] - offset[2]; SV_RecursiveHullCheck(pHull, pHull->firstclipnode, 0.0, 1.0, start_l, end_l, trace); @@ -127,14 +127,13 @@ int PM_HullPointContents(hull_t *hull, int num, vec_t *p) if (num < hull->firstclipnode || num > hull->lastclipnode) Sys_Error("PM_HullPointContents: bad node number"); node = &hull->clipnodes[num]; - plane = &hull->planes[hull->clipnodes[num].planenum]; + plane = &hull->planes[node->planenum]; - double tmpDist; if (plane->type >= 3) - tmpDist = plane->normal[2] * p[2] + plane->normal[1] * p[1] + plane->normal[0] * *p; + d = _DotProduct(p, plane->normal) - plane->dist; else - tmpDist = p[plane->type]; - d = (float)(tmpDist - plane->dist); + d = p[plane->type] - plane->dist; + if (d >= 0.0) num = node->children[0]; else @@ -331,13 +330,13 @@ int _PM_TestPlayerPosition(vec_t *pos, pmtrace_t *ptrace, int(*pfnIgnore)(physen test[2] = pos[2] - offset[2]; if (pe->solid == 4 && (pe->angles[0] != 0.0 || pe->angles[1] != 0.0 || pe->angles[2] != 0.0)) { - vec3_t forward, right, up, temp; - + vec3_t forward, right, up; AngleVectors(pe->angles, forward, right, up); - temp[0] = test[0]; temp[1] = test[1]; temp[2] = test[2]; - test[0] = forward[2] * test[2] + forward[1] * test[1] + forward[0] * test[0]; - test[1] = -(right[0] * temp[0] + right[2] * test[2] + right[1] * test[1]); - test[2] = up[1] * temp[1] + up[0] * temp[0] + up[2] * test[2]; + + vec3_t temp = {test[0], test[1], test[2]}; + test[0] = _DotProduct(forward, temp); + test[1] = -_DotProduct(right, temp); + test[2] = _DotProduct(up, temp); } if (numhulls != 1) { @@ -480,18 +479,20 @@ pmtrace_t _PM_PlayerTrace(vec_t *start, vec_t *end, int traceFlags, int numphyse if (pe->solid == SOLID_BSP && (pe->angles[0] != 0.0 || pe->angles[1] != 0.0 || pe->angles[2] != 0.0)) { - vec3_t temp, forward, right, up; - rotated = true; + vec3_t forward, right, up; AngleVectors(pe->angles, forward, right, up); - temp[0] = start_l[0]; temp[1] = start_l[1]; temp[2] = start_l[2]; - start_l[0] = forward[2] * start_l[2] + forward[1] * start_l[1] + forward[0] * start_l[0]; - start_l[1] = -(right[0] * temp[0] + right[2] * start_l[2] + right[1] * start_l[1]); - start_l[2] = up[1] * temp[1] + up[0] * temp[0] + up[2] * start_l[2]; - temp[0] = end_l[0]; temp[1] = end_l[1]; temp[2] = end_l[2]; - end_l[0] = forward[2] * end_l[2] + forward[1] * end_l[1] + forward[0] * end_l[0]; - end_l[1] = -(right[0] * temp[0] + right[2] * end_l[2] + right[1] * end_l[1]); - end_l[2] = up[1] * temp[1] + up[0] * temp[0] + up[2] * end_l[2]; + vec3_t temp_start = {start_l[0], start_l[1], start_l[2]}; + start_l[0] = _DotProduct(forward, temp_start); + start_l[1] = -_DotProduct(right, temp_start); + start_l[2] = _DotProduct(up, temp_start); + + vec3_t temp_end = {end_l[0], end_l[1], end_l[2]}; + end_l[0] = _DotProduct(forward, temp_end); + end_l[1] = -_DotProduct(right, temp_end); + end_l[2] = _DotProduct(up, temp_end); + + rotated = true; } else { @@ -550,13 +551,13 @@ pmtrace_t _PM_PlayerTrace(vec_t *start, vec_t *end, int traceFlags, int numphyse { if (rotated) { - vec3_t temp, forward, right, up; + vec3_t forward, right, up; AngleVectorsTranspose(pe->angles, forward, right, up); - temp[0] = total.plane.normal[0]; temp[1] = total.plane.normal[1]; temp[2] = total.plane.normal[2]; - total.plane.normal[0] = forward[2] * total.plane.normal[2] + forward[1] * total.plane.normal[1] + forward[0] * total.plane.normal[0]; - total.plane.normal[1] = right[2] * total.plane.normal[2] + right[1] * total.plane.normal[1] + right[0] * temp[0]; - total.plane.normal[2] = up[2] * total.plane.normal[2] + up[1] * temp[1] + up[0] * temp[0]; + vec3_t temp = {total.plane.normal[0], total.plane.normal[1], total.plane.normal[2]}; + total.plane.normal[0] = _DotProduct(forward, temp); + total.plane.normal[1] = _DotProduct(right, temp); + total.plane.normal[2] = _DotProduct(up, temp); } total.endpos[0] = (end[0] - start[0]) * total.fraction + start[0]; total.endpos[1] = (end[1] - start[1]) * total.fraction + start[1]; @@ -601,21 +602,13 @@ struct pmtrace_s *PM_TraceLine(float *start, float *end, int flags, int usehull, if (flags) { if (flags == 1) - { tr = _PM_PlayerTrace(start, end, 0, pmove->numvisent, pmove->visents, ignore_pe, 0); - pmove->usehull = oldhull; - } - else - { - pmove->usehull = oldhull; - } } else { tr = _PM_PlayerTrace(start, end, 0, pmove->numphysent, pmove->physents, ignore_pe, 0); - pmove->usehull = oldhull; } - + pmove->usehull = oldhull; return &tr; } @@ -629,15 +622,13 @@ struct pmtrace_s *PM_TraceLineEx(float *start, float *end, int flags, int usehul pmove->usehull = usehull; if (flags) { - tr = _PM_PlayerTrace(start, end, 0, pmove->numvisent, pmove->visents, -1, pfnIgnore); - pmove->usehull = oldhull; - + tr = _PM_PlayerTrace(start, end, 0, pmove->numvisent, pmove->visents, -1, pfnIgnore); } else { tr = PM_PlayerTraceEx(start, end, 0, pfnIgnore); - pmove->usehull = oldhull; } + pmove->usehull = oldhull; return &tr; } @@ -954,4 +945,4 @@ qboolean PM_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, cons return 0; } -#endif // REHLDS_OPT_PEDANTIC +#endif // REHLDS_OPT_PEDANTIC \ No newline at end of file diff --git a/rehlds/engine/pr_cmds.cpp b/rehlds/engine/pr_cmds.cpp index f9eb06f..a94967a 100644 --- a/rehlds/engine/pr_cmds.cpp +++ b/rehlds/engine/pr_cmds.cpp @@ -459,8 +459,8 @@ msurface_t *SurfaceAtPoint(model_t *pModel, mnode_t *node, vec_t *start, vec_t * return 0; plane = node->plane; - front = start[2] * plane->normal[2] + plane->normal[0] * start[0] + start[1] * plane->normal[1] - plane->dist; - back = plane->normal[0] * end[0] + plane->normal[2] * end[2] + plane->normal[1] * end[1] - plane->dist; + front = _DotProduct(start, plane->normal) - plane->dist; + back = _DotProduct(end, plane->normal) - plane->dist; s = (front < 0.0f) ? 1 : 0; t = (back < 0.0f) ? 1 : 0; if (t == s) @@ -481,8 +481,8 @@ msurface_t *SurfaceAtPoint(model_t *pModel, mnode_t *node, vec_t *start, vec_t * { surf = &pModel->surfaces[node->firstsurface + i]; tex = surf->texinfo; - ds = (int)(mid[2] * tex->vecs[0][2] + mid[1] * tex->vecs[0][1] + mid[0] * tex->vecs[0][0] + tex->vecs[0][3]); - dt = (int)(mid[2] * tex->vecs[1][2] + mid[1] * tex->vecs[1][1] + mid[0] * tex->vecs[1][0] + tex->vecs[1][3]); + ds = (int)_DotProduct(mid, tex->vecs[0]); + dt = (int)_DotProduct(mid, tex->vecs[1]); if (ds >= surf->texturemins[0]) { if (dt >= surf->texturemins[1]) @@ -532,14 +532,14 @@ const char *TraceTexture(edict_t *pTextureEntity, const float *v1, const float * AngleVectors(pTextureEntity->v.angles, forward, right, up); temp[0] = start[0]; temp[1] = start[1]; temp[2] = start[2]; - start[0] = forward[2] * start[2] + forward[1] * start[1] + forward[0] * start[0]; - start[1] = -(right[0] * temp[0] + right[2] * start[2] + right[1] * start[1]); - start[2] = up[1] * temp[1] + up[0] * temp[0] + up[2] * start[2]; + start[0] = _DotProduct(forward, temp); + start[1] = -_DotProduct(right, temp); + start[2] = _DotProduct(up, temp); temp[0] = end[0]; temp[1] = end[1]; temp[2] = end[2]; - end[0] = forward[2] * end[2] + forward[1] * end[1] + forward[0] * end[0]; - end[1] = -(right[0] * temp[0] + right[2] * end[2] + right[1] * end[1]); - end[2] = up[1] * temp[1] + up[0] * temp[0] + up[2] * end[2]; + end[0] = _DotProduct(forward, temp); + end[1] = -_DotProduct(right, temp); + end[2] = _DotProduct(up, temp); } } else @@ -1933,10 +1933,10 @@ edict_t *PF_CreateFakeClient_I(const char *netname) ent->v.pContainingEntity = ent; ent->v.flags = FL_FAKECLIENT | FL_CLIENT; - Info_SetValueForKey(fakeclient->userinfo, "name", netname, 256); - Info_SetValueForKey(fakeclient->userinfo, "model", "gordon", 256); - Info_SetValueForKey(fakeclient->userinfo, "topcolor", "1", 256); - Info_SetValueForKey(fakeclient->userinfo, "bottomcolor", "1", 256); + Info_SetValueForKey(fakeclient->userinfo, "name", netname, MAX_INFO_STRING); + Info_SetValueForKey(fakeclient->userinfo, "model", "gordon", MAX_INFO_STRING); + Info_SetValueForKey(fakeclient->userinfo, "topcolor", "1", MAX_INFO_STRING); + Info_SetValueForKey(fakeclient->userinfo, "bottomcolor", "1", MAX_INFO_STRING); fakeclient->sendinfo = 1; SV_ExtractFromUserinfo(fakeclient); diff --git a/rehlds/engine/sv_phys.cpp b/rehlds/engine/sv_phys.cpp index d7f44e7..e9bd903 100644 --- a/rehlds/engine/sv_phys.cpp +++ b/rehlds/engine/sv_phys.cpp @@ -193,7 +193,7 @@ int ClipVelocity(vec_t *in, vec_t *normal, vec_t *out, float overbounce) if (normal[2] == 0.0) blocked |= 2u; - float backoff = (in[0] * normal[0] + in[1] * normal[1] + normal[2] * in[2]) * overbounce; + float backoff = _DotProduct(in, normal) * overbounce; for (int i = 0; i < 3; i++) { float tmp = normal[i] * backoff; @@ -231,7 +231,7 @@ int SV_FlyMove(edict_t *ent, float time, trace_t *steptrace) vec3_t end; for (int i = 0; i < 3; i++) - end[i] = time * ent->v.velocity[i] + ent->v.origin[i]; + VectorMA(ent->v.origin, time, ent->v.velocity, end); trace_t trace = SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, end, 0, ent, monsterClip); if (trace.allsolid) @@ -314,7 +314,7 @@ int SV_FlyMove(edict_t *ent, float time, trace_t *steptrace) if (j == i) continue; - if (new_velocity[2] * planes[j][2] + new_velocity[0] * planes[j][0] + new_velocity[1] * planes[j][1] < 0.0f) + if (_DotProduct(new_velocity, planes[j]) < 0.0f) break; } if (j == numplanes) @@ -326,8 +326,8 @@ int SV_FlyMove(edict_t *ent, float time, trace_t *steptrace) return blocked; vec3_t dir; - CrossProduct((const vec_t *)planes, planes[1], dir); - float vscale = dir[2] * ent->v.velocity[2] + dir[0] * ent->v.velocity[0] + dir[1] * ent->v.velocity[1]; + CrossProduct(planes[0], planes[1], dir); + float vscale = _DotProduct(dir, ent->v.velocity); VectorScale(dir, vscale, ent->v.velocity); } else @@ -337,9 +337,7 @@ int SV_FlyMove(edict_t *ent, float time, trace_t *steptrace) ent->v.velocity[0] = new_velocity[0]; } - if (original_velocity[2] * ent->v.velocity[2] - + original_velocity[0] * ent->v.velocity[0] - + original_velocity[1] * ent->v.velocity[1] <= 0.0f) + if (_DotProduct(original_velocity, ent->v.velocity) <= 0.0f) { ent->v.velocity[0] = vec3_origin[0]; ent->v.velocity[1] = vec3_origin[1]; @@ -417,7 +415,7 @@ trace_t SV_PushEntity(edict_t *ent, vec_t *push) vec3_t end; // 518 int moveType; - end[0] = ent->v.origin[0] + push[0]; + end[0] = push[0] + ent->v.origin[0]; end[1] = push[1] + ent->v.origin[1]; end[2] = push[2] + ent->v.origin[2]; @@ -637,7 +635,7 @@ int SV_PushRotate(edict_t *pusher, float movetime) Sys_Error("Out of edicts in simulator!\n"); vec3_t start, end, push, move; - float start_off2; + if (check->v.movetype == MOVETYPE_PUSHSTEP) { vec3_t org; @@ -646,24 +644,23 @@ int SV_PushRotate(edict_t *pusher, float movetime) org[2] = (check->v.absmax[2] + check->v.absmin[2]) * 0.5f; start[0] = org[0] - pusher->v.origin[0]; start[1] = org[1] - pusher->v.origin[1]; - start_off2 = org[2]; + start[2] = org[2] - pusher->v.origin[2]; } else { start[0] = check->v.origin[0] - pusher->v.origin[0]; start[1] = check->v.origin[1] - pusher->v.origin[1]; - start_off2 = check->v.origin[2]; + start[2] = check->v.origin[2] - pusher->v.origin[2]; } - start[2] = start_off2 - pusher->v.origin[2]; pusher->v.solid = SOLID_NOT; - move[0] = forward[2] * start[2] + forward[1] * start[1] + forward[0] * start[0]; - move[1] = -(right[2] * start[2] + right[1] * start[1] + right[0] * start[0]); - move[2] = up[2] * start[2] + up[1] * start[1] + up[0] * start[0]; - end[0] = forwardNow[2] * move[2] + forwardNow[1] * move[1] + forwardNow[0] * move[0]; - end[1] = rightNow[2] * move[2] + rightNow[1] * move[1] + rightNow[0] * move[0]; - end[2] = upNow[2] * move[2] + upNow[1] * move[1] + upNow[0] * move[0]; + move[0] = _DotProduct(forward, start); + move[1] = -_DotProduct(right, start); + move[2] = _DotProduct(up, start); + end[0] = _DotProduct(forwardNow, move); + end[1] = _DotProduct(rightNow, move); + end[2] = _DotProduct(upNow, move); push[0] = end[0] - start[0]; push[1] = end[1] - start[1]; push[2] = end[2] - start[2]; @@ -1113,12 +1110,13 @@ void SV_Physics_Toss(edict_t *ent) ent->v.groundentity = trace.ent; } - if (move[2] * move[2] + move[1] * move[1] + move[0] * move[0] >= 900.0f) + if (_DotProduct(move, move) >= 900.0f) { if (ent->v.movetype == MOVETYPE_BOUNCE || ent->v.movetype == MOVETYPE_BOUNCEMISSILE) { - VectorScale(ent->v.velocity, (float)((1.0 - trace.fraction) * host_frametime * 0.9f), move); - VectorMA(move, (float)((1.0 - trace.fraction) * host_frametime * 0.9f), ent->v.basevelocity, move); + float scale = (1.0 - trace.fraction) * host_frametime * 0.9f; + VectorScale(ent->v.velocity, scale, move); + VectorMA(move, scale, ent->v.basevelocity, move); SV_PushEntity(ent, move); SV_CheckWaterTransition(ent); return; @@ -1154,10 +1152,10 @@ void PF_WaterMove(edict_t *pSelf) if (pSelf->v.health < 0.0) return; - drownlevel = (pSelf->v.deadflag) ? 1.0f : 3.0f; - flags = pSelf->v.flags; + drownlevel = pSelf->v.deadflag ? 1.0f : 3.0f; waterlevel = pSelf->v.waterlevel; watertype = pSelf->v.watertype; + flags = pSelf->v.flags; if (!(flags & (FL_IMMUNE_WATER | FL_GODMODE))) { if (flags & FL_SWIM && (waterlevel < drownlevel) diff --git a/rehlds/public/rehlds/osconfig.h b/rehlds/public/rehlds/osconfig.h index 08a2273..2494149 100644 --- a/rehlds/public/rehlds/osconfig.h +++ b/rehlds/public/rehlds/osconfig.h @@ -95,6 +95,7 @@ #define STDCALL __stdcall #define HIDDEN #define NOINLINE __declspec(noinline) + #define ALIGN16 __declspec(align(16)) //inline bool SOCKET_FIONBIO(SOCKET s, int m) { return (ioctlsocket(s, FIONBIO, (u_long*)&m) == 0); } //inline int SOCKET_MSGLEN(SOCKET s, u_long& r) { return ioctlsocket(s, FIONREAD, (u_long*)&r); } @@ -129,6 +130,7 @@ #define STDCALL __attribute__ ((stdcall)) #define HIDDEN __attribute__((visibility("hidden"))) #define NOINLINE __attribute__((noinline)) + #define ALIGN16 __attribute__((aligned(16))) //inline bool SOCKET_FIONBIO(SOCKET s, int m) { return (ioctl(s, FIONBIO, (int*)&m) == 0); } //inline int SOCKET_MSGLEN(SOCKET s, u_long& r) { return ioctl(s, FIONREAD, (int*)&r); } From 4b1eabc5416e2bdb2cc9ef7aee33d09d2ad403e2 Mon Sep 17 00:00:00 2001 From: dreamstalker Date: Fri, 15 May 2015 23:20:04 +0400 Subject: [PATCH 2/3] Mathlib unit tests Added REHLDS_OP_PEDANTIC define to all configs in the msvc project Fixed CrossProduct --- .gitignore | 2 + .../include/cppunitlite/Assertions.h | 2 + dep/cppunitlite/include/cppunitlite/Test.h | 8 +- dep/cppunitlite/src/Assertions.cpp | 11 +- msvc/ReHLDS.sln | 7 + rehlds/engine/mathlib.cpp | 10 +- rehlds/msvc/ReHLDS.vcxproj | 86 +++++- rehlds/msvc/ReHLDS.vcxproj.filters | 3 + rehlds/unittests/mathlib_tests.cpp | 283 ++++++++++++++++++ 9 files changed, 392 insertions(+), 20 deletions(-) create mode 100644 rehlds/unittests/mathlib_tests.cpp diff --git a/.gitignore b/.gitignore index 212e6ec..a2d9bd4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ *.iml **/msvc/Debug* **/msvc/Release* +**/msvc/Tests +**/msvc/Test Fixes **/msvc/*.sdf **/msvc/*.opensdf **/msvc/*.user diff --git a/dep/cppunitlite/include/cppunitlite/Assertions.h b/dep/cppunitlite/include/cppunitlite/Assertions.h index b191559..3974024 100644 --- a/dep/cppunitlite/include/cppunitlite/Assertions.h +++ b/dep/cppunitlite/include/cppunitlite/Assertions.h @@ -15,4 +15,6 @@ public: static void UInt32Equals(std::string message, unsigned int expected, unsigned int actual, const char* fileName, long lineNumber); static void CharEquals(std::string message, char expected, char actual, const char* fileName, long lineNumber); + + static void DoubleEquals(std::string message, double expected, double actual, double epsilon, const char* fileName, long lineNumber); }; diff --git a/dep/cppunitlite/include/cppunitlite/Test.h b/dep/cppunitlite/include/cppunitlite/Test.h index 9f18329..5b9561a 100644 --- a/dep/cppunitlite/include/cppunitlite/Test.h +++ b/dep/cppunitlite/include/cppunitlite/Test.h @@ -70,12 +70,8 @@ protected: { Assertions::CharEquals(msg,expected, actual, __FILE__, __LINE__); } -#define DOUBLES_EQUAL(expected,actual,threshold)\ -{ double actualTemp = actual; \ - double expectedTemp = expected; \ - if (fabs ((expectedTemp)-(actualTemp)) > threshold) \ -{ result_.addFailure (Failure (name_, __FILE__, __LINE__, \ -StringFrom((double)expectedTemp), StringFrom((double)actualTemp))); return; } } +#define DOUBLES_EQUAL(msg, expected,actual,threshold)\ +{ Assertions::DoubleEquals(msg,expected, actual, threshold, __FILE__, __LINE__); } diff --git a/dep/cppunitlite/src/Assertions.cpp b/dep/cppunitlite/src/Assertions.cpp index e856de7..ada346a 100644 --- a/dep/cppunitlite/src/Assertions.cpp +++ b/dep/cppunitlite/src/Assertions.cpp @@ -1,6 +1,7 @@ #include "cppunitlite/Assertions.h" #include +#include #include #include @@ -53,4 +54,12 @@ void Assertions::CharEquals(std::string message, char expected, char actual, con ss << message << " (expected '" << expected << "', got '" << actual << "')"; throw TestFailException(ss.str(), std::string(fileName), lineNumber); } -} \ No newline at end of file +} + +void Assertions::DoubleEquals(std::string message, double expected, double actual, double epsilon, const char* fileName, long lineNumber) { + if (abs(expected - actual) > epsilon) { + std::stringstream ss; + ss << message << " (expected '" << expected << "', got '" << actual << "')"; + throw TestFailException(ss.str(), std::string(fileName), lineNumber); + } +} diff --git a/msvc/ReHLDS.sln b/msvc/ReHLDS.sln index cf5e61d..b1aff52 100644 --- a/msvc/ReHLDS.sln +++ b/msvc/ReHLDS.sln @@ -30,6 +30,7 @@ Global Debug|Win32 = Debug|Win32 Release Play|Win32 = Release Play|Win32 Release|Win32 = Release|Win32 + Test Fixes|Win32 = Test Fixes|Win32 Tests|Win32 = Tests|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution @@ -47,6 +48,8 @@ Global {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Release Play|Win32.Build.0 = Release Play|Win32 {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Release|Win32.ActiveCfg = Release|Win32 {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Release|Win32.Build.0 = Release|Win32 + {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Test Fixes|Win32.ActiveCfg = Test Fixes|Win32 + {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Test Fixes|Win32.Build.0 = Test Fixes|Win32 {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Tests|Win32.ActiveCfg = Tests|Win32 {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Tests|Win32.Build.0 = Tests|Win32 {CEB94F7C-E459-4673-AABB-36E2074396C0}.Debug Play|Win32.ActiveCfg = Debug|Win32 @@ -63,6 +66,8 @@ Global {CEB94F7C-E459-4673-AABB-36E2074396C0}.Release Play|Win32.Build.0 = Release|Win32 {CEB94F7C-E459-4673-AABB-36E2074396C0}.Release|Win32.ActiveCfg = Release|Win32 {CEB94F7C-E459-4673-AABB-36E2074396C0}.Release|Win32.Build.0 = Release|Win32 + {CEB94F7C-E459-4673-AABB-36E2074396C0}.Test Fixes|Win32.ActiveCfg = Debug|Win32 + {CEB94F7C-E459-4673-AABB-36E2074396C0}.Test Fixes|Win32.Build.0 = Debug|Win32 {CEB94F7C-E459-4673-AABB-36E2074396C0}.Tests|Win32.ActiveCfg = Debug|Win32 {CEB94F7C-E459-4673-AABB-36E2074396C0}.Tests|Win32.Build.0 = Debug|Win32 {792DF067-9904-4579-99B9-46C17277ADE3}.Debug Play|Win32.ActiveCfg = Debug|Win32 @@ -79,6 +84,8 @@ Global {792DF067-9904-4579-99B9-46C17277ADE3}.Release Play|Win32.Build.0 = Release|Win32 {792DF067-9904-4579-99B9-46C17277ADE3}.Release|Win32.ActiveCfg = Release|Win32 {792DF067-9904-4579-99B9-46C17277ADE3}.Release|Win32.Build.0 = Release|Win32 + {792DF067-9904-4579-99B9-46C17277ADE3}.Test Fixes|Win32.ActiveCfg = Debug|Win32 + {792DF067-9904-4579-99B9-46C17277ADE3}.Test Fixes|Win32.Build.0 = Debug|Win32 {792DF067-9904-4579-99B9-46C17277ADE3}.Tests|Win32.ActiveCfg = Debug|Win32 {792DF067-9904-4579-99B9-46C17277ADE3}.Tests|Win32.Build.0 = Debug|Win32 EndGlobalSection diff --git a/rehlds/engine/mathlib.cpp b/rehlds/engine/mathlib.cpp index 4e986be..72b5a1c 100644 --- a/rehlds/engine/mathlib.cpp +++ b/rehlds/engine/mathlib.cpp @@ -398,15 +398,15 @@ void CrossProduct(const vec_t *v1, const vec_t *v2, vec_t *cross) { #ifdef REHLDS_FIXES __m128 a = _mm_loadu_ps(v1), b = _mm_loadu_ps(v2); - __m128 m = _mm_sub_ps( _mm_mul_ps(b, _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1))), - _mm_mul_ps(a, _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1))) - ); + __m128 tmp1 = _mm_mul_ps(a, _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1))); + __m128 tmp2 = _mm_mul_ps(b, _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1))); + __m128 m = _mm_sub_ps(tmp1, tmp2); xmm2vec(cross, _mm_shuffle_ps(m, m, _MM_SHUFFLE(3, 0, 2, 1))); #else // REHLDS_FIXES - cross[0] = v2[2] * v1[1] - v1[2] * v2[1]; + cross[0] = v1[1] * v2[2] - v1[2] * v2[1]; cross[1] = v1[2] * v2[0] - v1[0] * v2[2]; - cross[2] = v1[0] * v2[1] - v2[0] * v1[1]; + cross[2] = v1[0] * v2[1] - v1[1] * v2[0]; #endif // REHLDS_FIXES } diff --git a/rehlds/msvc/ReHLDS.vcxproj b/rehlds/msvc/ReHLDS.vcxproj index 9addf4f..30d485e 100644 --- a/rehlds/msvc/ReHLDS.vcxproj +++ b/rehlds/msvc/ReHLDS.vcxproj @@ -29,6 +29,10 @@ Release Win32 + + Test Fixes + Win32 + Tests Win32 @@ -91,11 +95,13 @@ true + true true true true + true true true @@ -108,6 +114,7 @@ true true true + true true false true @@ -125,6 +132,7 @@ true true true + true @@ -136,6 +144,7 @@ true true true + true true @@ -146,6 +155,7 @@ true true true + true @@ -158,6 +168,7 @@ true true true + true @@ -183,7 +194,9 @@ precompiled.h precompiled.h Create + Create precompiled.h + precompiled.h @@ -201,12 +214,20 @@ true true + + true + true + true + true + true + true true true true false + false true @@ -469,6 +490,7 @@ true true true + true true @@ -477,6 +499,7 @@ true true true + true @@ -528,6 +551,12 @@ v120_xp MultiByte + + Application + true + v120_xp + MultiByte + DynamicLibrary false @@ -563,6 +592,9 @@ + + + @@ -588,6 +620,9 @@ filesystem_stdio + + filesystem_stdio + filesystem_stdio @@ -604,7 +639,7 @@ Level3 Disabled true - REHLDS_SELF;HOOK_ENGINE;REHLDS_FIXES;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;REHLDS_FIXES;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) Precise /arch:IA32 %(AdditionalOptions) MultiThreadedDebug @@ -642,7 +677,7 @@ Level3 Disabled true - REHLDS_SELF;REHLDS_FIXES;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + REHLDS_OPT_PEDANTIC;REHLDS_SELF;REHLDS_FIXES;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) Precise /arch:IA32 %(AdditionalOptions) MultiThreadedDebug @@ -679,7 +714,7 @@ Level3 Disabled true - REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) Precise /arch:IA32 %(AdditionalOptions) MultiThreadedDebug @@ -715,7 +750,7 @@ Level3 Disabled true - REHLDS_SELF;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + REHLDS_OPT_PEDANTIC;REHLDS_SELF;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) Precise /arch:IA32 %(AdditionalOptions) MultiThreadedDebug @@ -754,7 +789,7 @@ Level3 Disabled true - REHLDS_SELF;HOOK_ENGINE;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) Precise /arch:IA32 %(AdditionalOptions) MultiThreadedDebug @@ -790,7 +825,7 @@ Level3 Disabled true - REHLDS_SELF;_BUILD_FROM_IDE;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + REHLDS_OPT_PEDANTIC;REHLDS_SELF;_BUILD_FROM_IDE;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) MultiThreadedDebug Use precompiled.h @@ -815,6 +850,41 @@ subversion.always.run + + + IF EXIST "$(ProjectDir)PreBuild.bat" (CALL "$(ProjectDir)PreBuild.bat" "$(ProjectDir)..\version\" "$(ProjectDir)..\") + Setup version from SVN revision + + + $(ProjectDir)\..\;$(ProjectDir)\..\hookers\;$(ProjectDir)\..\metamod\include\;$(ProjectDir)\..\public\rehlds\;$(ProjectDir)\..\common;$(ProjectDir)\..\engine;$(ProjectDir)\..\public;$(ProjectDir)\..\pm_shared;$(ProjectDir)\..\rehlds\;$(ProjectDir)\..\testsuite\;$(VCInstallDir)UnitTest\include;$(SolutionDir)..\dep\bzip2\include\;$(SolutionDir)..\dep\cppunitlite\include\;%(AdditionalIncludeDirectories) + Level3 + Disabled + true + REHLDS_OPT_PEDANTIC;REHLDS_FIXES;REHLDS_SELF;_BUILD_FROM_IDE;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions) + MultiThreadedDebug + Use + precompiled.h + + + true + psapi.lib;ws2_32.lib;$(ProjectDir)../lib/steam_api.lib;%(AdditionalDependencies) + + + + + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + copy /Y "$(ProjectDir)..\lib\steam_api.dll" "$(OutDir)" + Automatic deployment script + + + echo Empty Action + Force build to run Pre-Build event + subversion.always.run + subversion.always.run + + IF EXIST "$(ProjectDir)PreBuild.bat" (CALL "$(ProjectDir)PreBuild.bat" "$(ProjectDir)..\version\" "$(ProjectDir)..\") @@ -827,7 +897,7 @@ true true true - REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreaded /arch:IA32 %(AdditionalOptions) Use @@ -866,7 +936,7 @@ true true true - REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreaded /arch:IA32 %(AdditionalOptions) Use diff --git a/rehlds/msvc/ReHLDS.vcxproj.filters b/rehlds/msvc/ReHLDS.vcxproj.filters index b5eb9bd..84bece4 100644 --- a/rehlds/msvc/ReHLDS.vcxproj.filters +++ b/rehlds/msvc/ReHLDS.vcxproj.filters @@ -322,6 +322,9 @@ engine + + unittests + diff --git a/rehlds/unittests/mathlib_tests.cpp b/rehlds/unittests/mathlib_tests.cpp new file mode 100644 index 0000000..fbb2658 --- /dev/null +++ b/rehlds/unittests/mathlib_tests.cpp @@ -0,0 +1,283 @@ +#include "precompiled.h" +#include "cppunitlite/TestHarness.h" + +TEST(AngleVectorsTest, MathLib, 1000) { + Sys_CheckCpuInstructionsSupport(); + CHECK("SSE4.1 Support", cpuinfo.sse4_1); + + struct testdata_t { + vec3_t angles; + vec3_t forward, right, up; + }; + + testdata_t testdata[2] = { + { { 21.0f, 65.0f, 162.0f }, { 0.39455f, 0.84611f, -0.35837f }, { -0.90875f, 0.30156f, -0.28849f }, { 0.13602f, -0.43949f, -0.88789f } }, + { { 106.0f, 142.0f, 62.0f }, { 0.21721f, -0.16970f, -0.96126f }, { 0.95785f, -0.15259f, 0.24337f }, { 0.18798f, 0.97361f, -0.12940f } } + }; + + for (int sse = 0; sse <= 1; sse++) { + vec3_t forward, right, up; + + for (int i = 0; i < ARRAYSIZE(testdata); i++) { + AngleVectors(testdata[i].angles, forward, right, up); + + DOUBLES_EQUAL("forward[0] mismatch", testdata[i].forward[0], forward[0], 0.00001); + DOUBLES_EQUAL("forward[1] mismatch", testdata[i].forward[1], forward[1], 0.00001); + DOUBLES_EQUAL("forward[2] mismatch", testdata[i].forward[2], forward[2], 0.00001); + + DOUBLES_EQUAL("right[0] mismatch", testdata[i].right[0], right[0], 0.00001); + DOUBLES_EQUAL("right[1] mismatch", testdata[i].right[1], right[1], 0.00001); + DOUBLES_EQUAL("right[2] mismatch", testdata[i].right[2], right[2], 0.00001); + + DOUBLES_EQUAL("up[0] mismatch", testdata[i].up[0], up[0], 0.00001); + DOUBLES_EQUAL("up[1] mismatch", testdata[i].up[1], up[1], 0.00001); + DOUBLES_EQUAL("up[2] mismatch", testdata[i].up[2], up[2], 0.00001); + } + + cpuinfo.sse4_1 = 0; + } +} + +TEST(AngleVectorsTransposeTest, MathLib, 1000) { + Sys_CheckCpuInstructionsSupport(); + CHECK("SSE4.1 Support", cpuinfo.sse4_1); + + struct testdata_t { + vec3_t angles; + vec3_t forward, right, up; + }; + + testdata_t testdata[2] = { + { { 21.0f, 65.0f, 162.0f }, { 0.39455f, 0.90875f, 0.13602f }, { 0.84611f, -0.30157f, -0.43949f }, { -0.35837f, 0.28849f, -0.88789f } }, + { { 106.0f, 142.0f, 62.0f }, { 0.21721f, -0.95785f, 0.18798f }, { -0.16970f, 0.15259f, 0.97361f }, { -0.96126f, -0.24337f, -0.12940f } } + }; + + for (int sse = 0; sse <= 1; sse++) { + vec3_t forward, right, up; + + for (int i = 0; i < ARRAYSIZE(testdata); i++) { + AngleVectorsTranspose(testdata[i].angles, forward, right, up); + + DOUBLES_EQUAL("forward[0] mismatch", testdata[i].forward[0], forward[0], 0.00001); + DOUBLES_EQUAL("forward[1] mismatch", testdata[i].forward[1], forward[1], 0.00001); + DOUBLES_EQUAL("forward[2] mismatch", testdata[i].forward[2], forward[2], 0.00001); + + DOUBLES_EQUAL("right[0] mismatch", testdata[i].right[0], right[0], 0.00001); + DOUBLES_EQUAL("right[1] mismatch", testdata[i].right[1], right[1], 0.00001); + DOUBLES_EQUAL("right[2] mismatch", testdata[i].right[2], right[2], 0.00001); + + DOUBLES_EQUAL("up[0] mismatch", testdata[i].up[0], up[0], 0.00001); + DOUBLES_EQUAL("up[1] mismatch", testdata[i].up[1], up[1], 0.00001); + DOUBLES_EQUAL("up[2] mismatch", testdata[i].up[2], up[2], 0.00001); + } + + cpuinfo.sse4_1 = 0; + } +} + +TEST(AngleMatrixTest, MathLib, 1000) { + Sys_CheckCpuInstructionsSupport(); + CHECK("SSE4.1 Support", cpuinfo.sse4_1); + + struct testdata_t { + vec3_t angles; + vec_t matrix0[4]; + vec_t matrix1[4]; + vec_t matrix2[4]; + }; + + testdata_t testdata[2] = { + { { 21.0f, 65.0f, 162.0f }, { 0.39455f, 0.90875f, 0.13602f, 0.0f }, { 0.84611f, -0.30157f, -0.43949f, 0.0f }, { -0.35837f, 0.28849f, -0.88789f, 0.0f } }, + { { 106.0f, 142.0f, 62.0f }, { 0.21721f, -0.95785f, 0.18798f, 0.0f }, { -0.16970f, 0.15259f, 0.97361f, 0.0f }, { -0.96126f, -0.24337f, -0.12940f, 0.0f } } + }; + + for (int sse = 0; sse <= 1; sse++) { + float rotationmatrix[3][4]; + + for (int i = 0; i < ARRAYSIZE(testdata); i++) { + AngleMatrix(testdata[i].angles, rotationmatrix); + + DOUBLES_EQUAL("rotationmatrix[0][0] mismatch", testdata[i].matrix0[0], rotationmatrix[0][0], 0.00001); + DOUBLES_EQUAL("rotationmatrix[0][1] mismatch", testdata[i].matrix0[1], rotationmatrix[0][1], 0.00001); + DOUBLES_EQUAL("rotationmatrix[0][2] mismatch", testdata[i].matrix0[2], rotationmatrix[0][2], 0.00001); + DOUBLES_EQUAL("rotationmatrix[0][3] mismatch", testdata[i].matrix0[3], rotationmatrix[0][3], 0.00001); + + DOUBLES_EQUAL("rotationmatrix[1][0] mismatch", testdata[i].matrix1[0], rotationmatrix[1][0], 0.00001); + DOUBLES_EQUAL("rotationmatrix[1][1] mismatch", testdata[i].matrix1[1], rotationmatrix[1][1], 0.00001); + DOUBLES_EQUAL("rotationmatrix[1][2] mismatch", testdata[i].matrix1[2], rotationmatrix[1][2], 0.00001); + DOUBLES_EQUAL("rotationmatrix[1][3] mismatch", testdata[i].matrix1[3], rotationmatrix[1][3], 0.00001); + + DOUBLES_EQUAL("rotationmatrix[2][0] mismatch", testdata[i].matrix2[0], rotationmatrix[2][0], 0.00001); + DOUBLES_EQUAL("rotationmatrix[2][1] mismatch", testdata[i].matrix2[1], rotationmatrix[2][1], 0.00001); + DOUBLES_EQUAL("rotationmatrix[2][2] mismatch", testdata[i].matrix2[2], rotationmatrix[2][2], 0.00001); + DOUBLES_EQUAL("rotationmatrix[2][3] mismatch", testdata[i].matrix2[3], rotationmatrix[2][3], 0.00001); + } + + cpuinfo.sse4_1 = 0; + } +} + +TEST(DotProductTest, MathLib, 1000) { + Sys_CheckCpuInstructionsSupport(); + CHECK("SSE4.1 Support", cpuinfo.sse4_1); + + struct testdata_t { + vec3_t v1; + vec3_t v2; + float res; + }; + + testdata_t testdata[2] = { + { { 41.5f, 7.32f, -9.22f }, { 13.3f, -0.5f, 8.09f }, 473.70023f }, + { { -16.1f, -0.09f, 1.2f }, { 8.2f, 1.2f, -6.66f }, -140.12001f }, + }; + + for (int sse = 0; sse <= 1; sse++) { + + for (int i = 0; i < ARRAYSIZE(testdata); i++) { + double res = _DotProduct(testdata[i].v1, testdata[i].v2); + DOUBLES_EQUAL("_DotProduct mismatch", testdata[i].res, res, 0.00001); + } + + cpuinfo.sse4_1 = 0; + } +} + +TEST(CrossProductTest, MathLib, 1000) { + Sys_CheckCpuInstructionsSupport(); + CHECK("SSE4.1 Support", cpuinfo.sse4_1); + + struct testdata_t { + vec3_t v1; + vec3_t v2; + vec3_t res; + }; + + testdata_t testdata[2] = { + { { 41.5f, 7.32f, -9.22f }, { 13.3f, -0.5f, 8.09f }, { 54.60880f, -458.36102f, -118.10600f } }, + { { -16.1f, -0.09f, 1.2f }, { 8.2f, 1.2f, -6.66f }, { -0.84060f, -97.38600f, -18.58200f } }, + }; + + for (int sse = 0; sse <= 1; sse++) { + vec3_t res; + + for (int i = 0; i < ARRAYSIZE(testdata); i++) { + CrossProduct(testdata[i].v1, testdata[i].v2, res); + + DOUBLES_EQUAL("CrossProduct[0] mismatch", testdata[i].res[0], res[0], 0.00001); + DOUBLES_EQUAL("CrossProduct[1] mismatch", testdata[i].res[1], res[1], 0.00001); + DOUBLES_EQUAL("CrossProduct[2] mismatch", testdata[i].res[2], res[2], 0.00001); + } + + cpuinfo.sse4_1 = 0; + } +} + +TEST(LengthTest, MathLib, 1000) { + Sys_CheckCpuInstructionsSupport(); + CHECK("SSE4.1 Support", cpuinfo.sse4_1); + + struct testdata_t { + vec3_t v; + float l; + }; + + testdata_t testdata[2] = { + { { 41.5f, 7.32f, -9.22f }, 43.13746f }, + { { -16.1f, -0.09f, 1.2f }, 16.14491f }, + }; + + for (int sse = 0; sse <= 1; sse++) { + for (int i = 0; i < ARRAYSIZE(testdata); i++) { + double res = Length(testdata[i].v); + + DOUBLES_EQUAL("Length mismatch", testdata[i].l, res, 0.00001); + } + + cpuinfo.sse4_1 = 0; + } +} + +TEST(Length2DTest, MathLib, 1000) { + Sys_CheckCpuInstructionsSupport(); + CHECK("SSE4.1 Support", cpuinfo.sse4_1); + + struct testdata_t { + vec3_t v; + float l; + }; + + testdata_t testdata[2] = { + { { 41.5f, 7.32f, -9.22f }, 42.14063f }, + { { -16.1f, -0.09f, 1.2f }, 16.10025f }, + }; + + for (int sse = 0; sse <= 1; sse++) { + for (int i = 0; i < ARRAYSIZE(testdata); i++) { + double res = Length2D(testdata[i].v); + + DOUBLES_EQUAL("Length mismatch", testdata[i].l, res, 0.00001); + } + + cpuinfo.sse4_1 = 0; + } +} + +TEST(VectorNormalizeTest, MathLib, 1000) { + Sys_CheckCpuInstructionsSupport(); + CHECK("SSE4.1 Support", cpuinfo.sse4_1); + + struct testdata_t { + vec3_t vecIn; + vec3_t vecOut; + float l; + }; + + testdata_t testdata[2] = { + { { 41.5f, 7.32f, -9.22f }, { 0.96204f, 0.16969f, -0.21374f }, 43.13746f }, + { { -16.1f, -0.09f, 1.2f }, { -0.99722f, -0.00557f, 0.07433f }, 16.14491f }, + }; + + for (int sse = 0; sse <= 1; sse++) { + for (int i = 0; i < ARRAYSIZE(testdata); i++) { + vec3_t v; + memcpy(&v[0], &testdata[i].vecIn[0], sizeof(v)); + double res = VectorNormalize(v); + + DOUBLES_EQUAL("VectorNormalize.len mismatch", testdata[i].l, res, 0.00001); + DOUBLES_EQUAL("VectorNormalize[0] mismatch", testdata[i].vecOut[0], v[0], 0.00001); + DOUBLES_EQUAL("VectorNormalize[1] mismatch", testdata[i].vecOut[1], v[1], 0.00001); + DOUBLES_EQUAL("VectorNormalize[2] mismatch", testdata[i].vecOut[2], v[2], 0.00001); + } + + cpuinfo.sse4_1 = 0; + } +} + +TEST(VectorAnglesTest, MathLib, 1000) { + Sys_CheckCpuInstructionsSupport(); + CHECK("SSE4.1 Support", cpuinfo.sse4_1); + + struct testdata_t { + vec3_t forward; + vec3_t angles; + }; + + testdata_t testdata[2] = { + { { 0.96204f, 0.16969f, -0.21374f }, { 347.65839f, 10.00326f, 0.0f } }, + { { -0.99722f, -0.00557f, 0.07433f }, { 4.26272f, 180.32002f, 0.0f } }, + }; + + for (int sse = 0; sse <= 1; sse++) { + for (int i = 0; i < ARRAYSIZE(testdata); i++) { + vec3_t angles; + VectorAngles(testdata[i].forward, angles); + + DOUBLES_EQUAL("VectorAngles[0] mismatch", testdata[i].angles[0], angles[0], 0.00001); + DOUBLES_EQUAL("VectorAngles[1] mismatch", testdata[i].angles[1], angles[1], 0.00001); + DOUBLES_EQUAL("VectorAngles[2] mismatch", testdata[i].angles[2], angles[2], 0.00001); + } + + cpuinfo.sse4_1 = 0; + } +} \ No newline at end of file From 01f3fdf787f8f11e4731360a90b48b578b217174 Mon Sep 17 00:00:00 2001 From: dreamstalker Date: Sun, 17 May 2015 19:15:10 +0400 Subject: [PATCH 3/3] Fixed: there was a tiny chance to assemble corrupted svc_event message in SV_EmitEvents --- msvc/ReHLDS.sln | 7 ++++ rehlds/engine/sv_main.cpp | 4 ++ rehlds/msvc/ReHLDS.vcxproj | 76 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/msvc/ReHLDS.sln b/msvc/ReHLDS.sln index b1aff52..3af9f01 100644 --- a/msvc/ReHLDS.sln +++ b/msvc/ReHLDS.sln @@ -29,6 +29,7 @@ Global Debug Swds|Win32 = Debug Swds|Win32 Debug|Win32 = Debug|Win32 Release Play|Win32 = Release Play|Win32 + Release Swds Play|Win32 = Release Swds Play|Win32 Release|Win32 = Release|Win32 Test Fixes|Win32 = Test Fixes|Win32 Tests|Win32 = Tests|Win32 @@ -46,6 +47,8 @@ Global {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Debug|Win32.Build.0 = Debug|Win32 {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Release Play|Win32.ActiveCfg = Release Play|Win32 {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Release Play|Win32.Build.0 = Release Play|Win32 + {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Release Swds Play|Win32.ActiveCfg = Release Swds Play|Win32 + {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Release Swds Play|Win32.Build.0 = Release Swds Play|Win32 {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Release|Win32.ActiveCfg = Release|Win32 {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Release|Win32.Build.0 = Release|Win32 {70A2B904-B7DB-4C48-8DE0-AF567360D572}.Test Fixes|Win32.ActiveCfg = Test Fixes|Win32 @@ -64,6 +67,8 @@ Global {CEB94F7C-E459-4673-AABB-36E2074396C0}.Debug|Win32.Build.0 = Debug|Win32 {CEB94F7C-E459-4673-AABB-36E2074396C0}.Release Play|Win32.ActiveCfg = Release|Win32 {CEB94F7C-E459-4673-AABB-36E2074396C0}.Release Play|Win32.Build.0 = Release|Win32 + {CEB94F7C-E459-4673-AABB-36E2074396C0}.Release Swds Play|Win32.ActiveCfg = Release|Win32 + {CEB94F7C-E459-4673-AABB-36E2074396C0}.Release Swds Play|Win32.Build.0 = Release|Win32 {CEB94F7C-E459-4673-AABB-36E2074396C0}.Release|Win32.ActiveCfg = Release|Win32 {CEB94F7C-E459-4673-AABB-36E2074396C0}.Release|Win32.Build.0 = Release|Win32 {CEB94F7C-E459-4673-AABB-36E2074396C0}.Test Fixes|Win32.ActiveCfg = Debug|Win32 @@ -82,6 +87,8 @@ Global {792DF067-9904-4579-99B9-46C17277ADE3}.Debug|Win32.Build.0 = Debug|Win32 {792DF067-9904-4579-99B9-46C17277ADE3}.Release Play|Win32.ActiveCfg = Release|Win32 {792DF067-9904-4579-99B9-46C17277ADE3}.Release Play|Win32.Build.0 = Release|Win32 + {792DF067-9904-4579-99B9-46C17277ADE3}.Release Swds Play|Win32.ActiveCfg = Release|Win32 + {792DF067-9904-4579-99B9-46C17277ADE3}.Release Swds Play|Win32.Build.0 = Release|Win32 {792DF067-9904-4579-99B9-46C17277ADE3}.Release|Win32.ActiveCfg = Release|Win32 {792DF067-9904-4579-99B9-46C17277ADE3}.Release|Win32.Build.0 = Release|Win32 {792DF067-9904-4579-99B9-46C17277ADE3}.Test Fixes|Win32.ActiveCfg = Debug|Win32 diff --git a/rehlds/engine/sv_main.cpp b/rehlds/engine/sv_main.cpp index 7d5d9f0..57cb025 100644 --- a/rehlds/engine/sv_main.cpp +++ b/rehlds/engine/sv_main.cpp @@ -3828,6 +3828,10 @@ void SV_EmitEvents(client_t *cl, packet_entities_t *pack, sizebuf_t *msg) MSG_WriteBits(1, 1); DELTA_WriteDelta((byte *)&nullargs, (byte *)&info->args, TRUE, g_peventdelta, NULL); } + else + { + MSG_WriteBits(0, 1); + } } else { diff --git a/rehlds/msvc/ReHLDS.vcxproj b/rehlds/msvc/ReHLDS.vcxproj index 30d485e..f82e3ef 100644 --- a/rehlds/msvc/ReHLDS.vcxproj +++ b/rehlds/msvc/ReHLDS.vcxproj @@ -25,6 +25,10 @@ Release Play Win32 + + Release Swds Play + Win32 + Release Win32 @@ -98,21 +102,25 @@ true true true + true true true true true + true true true + true true true true + false true true true @@ -131,6 +139,7 @@ true true true + true true true @@ -143,6 +152,7 @@ true true true + true true true @@ -154,6 +164,7 @@ true true true + true true true @@ -167,6 +178,7 @@ true true true + true true true @@ -191,8 +203,10 @@ precompiled.h Create Create + Create precompiled.h precompiled.h + precompiled.h Create Create precompiled.h @@ -213,12 +227,14 @@ true true true + true true true true true + true true @@ -226,12 +242,14 @@ true true true + true false false true true + true true true true @@ -243,6 +261,7 @@ true true true + true @@ -571,6 +590,13 @@ true MultiByte + + DynamicLibrary + false + v120_xp + true + MultiByte + @@ -601,6 +627,9 @@ + + + filesystem_stdio @@ -629,6 +658,9 @@ filesystem_stdio + + swds + IF EXIST "$(ProjectDir)PreBuild.bat" (CALL "$(ProjectDir)PreBuild.bat" "$(ProjectDir)..\version\" "$(ProjectDir)..\") @@ -964,6 +996,50 @@ subversion.always.run + + + IF EXIST "$(ProjectDir)PreBuild.bat" (CALL "$(ProjectDir)PreBuild.bat" "$(ProjectDir)..\version\" "$(ProjectDir)..\") + Setup version from SVN revision + + + $(ProjectDir)\..\;$(ProjectDir)\..\hookers\;$(ProjectDir)\..\metamod\include\;$(ProjectDir)\..\public\rehlds\;$(ProjectDir)\..\common;$(ProjectDir)\..\engine;$(ProjectDir)\..\public;$(ProjectDir)\..\pm_shared;$(ProjectDir)\..\rehlds\;$(ProjectDir)\..\testsuite\;$(VCInstallDir)UnitTest\include;$(SolutionDir)..\dep\bzip2\include\;$(SolutionDir)..\dep\cppunitlite\include\;%(AdditionalIncludeDirectories) + Level3 + MaxSpeed + true + true + true + REHLDS_OPT_PEDANTIC;REHLDS_SELF;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + /arch:IA32 %(AdditionalOptions) + Use + precompiled.h + + + true + true + true + psapi.lib;ws2_32.lib;$(ProjectDir)../lib/steam_api.lib;%(AdditionalDependencies) + + + + + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + false + + + 0x4970000 + + + IF EXIST "$(ProjectDir)PostBuild_swds.bat" (CALL "$(ProjectDir)PostBuild_swds.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)") + Automatic deployment script + + + echo Empty Action + Force build to run Pre-Build event + subversion.always.run + subversion.always.run + +