2
0
mirror of https://github.com/rehlds/rehlds.git synced 2024-12-28 15:45:46 +03:00

Implemented delta JIT

Implemented name->index map for sv.model_precache[]
Fixed CPPUnitLite tests runner
Source code optimizations for optimal usage of precompiled headers on linux
This commit is contained in:
dreamstalker 2015-05-18 17:04:00 +04:00
parent 5d572afc31
commit 7891b6196a
43 changed files with 10094 additions and 125 deletions

1
.gitignore vendored
View File

@ -15,4 +15,5 @@
rehlds/version/appversion.h
rehlds/msvc/PublishPath*.txt
rehlds/_rehldsTestImg
rehlds/_dev
publish

View File

@ -4,6 +4,7 @@ class GradleAdapter {
public:
int writeAllTestsInfoToFile(const char* fname);
int runTest(const char* groupName, const char* testName);
int runGroup(const char* groupName);
int runAllTests();
int testsEntryPoint(int argc, char* argv[]);
};

View File

@ -35,7 +35,10 @@ int GradleAdapter::writeAllTestsInfoToFile(const char* fname) {
int GradleAdapter::runTest(const char* groupName, const char* testName) {
Test* curTest = TestRegistry::getFirstTest();
while (curTest != NULL && strcmp(groupName, curTest->getGroup()) && strcmp(testName, curTest->getGroup())) {
while (curTest != NULL) {
if (!strcmp(groupName, curTest->getGroup()) && !strcmp(testName, curTest->getName())) {
break;
}
curTest = curTest->getNext();
}
@ -55,11 +58,18 @@ int GradleAdapter::runTest(const char* groupName, const char* testName) {
}
}
int GradleAdapter::runAllTests() {
int GradleAdapter::runGroup(const char* groupName) {
Test* curTest = TestRegistry::getFirstTest();
int ranTests = 0;
while (curTest != NULL) {
if (strcmp(groupName, curTest->getGroup())) {
curTest = curTest->getNext();
continue;
}
TestResult result;
curTest->run(result);
ranTests++;
if (result.getFailureCount()) {
return 1;
@ -68,7 +78,31 @@ int GradleAdapter::runAllTests() {
curTest = curTest->getNext();
}
printf("There were no test failures\n");
if (ranTests == 0) {
printf("No tests with group='%s' found\n", groupName);
return 2;
}
printf("There were no test failures; Tests executed: %d\n", ranTests);
return 0;
}
int GradleAdapter::runAllTests() {
Test* curTest = TestRegistry::getFirstTest();
int ranTests = 0;
while (curTest != NULL) {
TestResult result;
curTest->run(result);
ranTests++;
if (result.getFailureCount()) {
return 1;
}
curTest = curTest->getNext();
}
printf("There were no test failures; Tests executed: %d\n", ranTests);
return 0;
}
@ -93,6 +127,14 @@ int GradleAdapter::testsEntryPoint(int argc, char* argv[]) {
return runTest(argv[2], argv[3]);
}
if (!strcmp(argv[1], "-runGroup")) {
if (argc != 3) {
printf("-runGroup requires group name\n");
}
return runGroup(argv[2]);
}
printf("Bad argument specified\n");
return 1;
}

View File

@ -21,6 +21,7 @@ void TestResult::addFailure (const Failure& failure) {
std::stringstream ss;
ss << "Failure in test '" << failure.testName << "' :" << failure.message;
std::cout << ss.str() << std::endl;
std::cout.flush();
failureCount++;
}
@ -33,4 +34,5 @@ void TestResult::testsEnded () {
ss << "There were no test failures";
}
std::cout << ss.str() << std::endl;
std::cout.flush();
}

View File

@ -31,19 +31,6 @@
#ifndef Defines_and_Variables_region
#define DT_BYTE BIT(0) // A byte
#define DT_SHORT BIT(1) // 2 byte field
#define DT_FLOAT BIT(2) // A floating point field
#define DT_INTEGER BIT(3) // 4 byte integer
#define DT_ANGLE BIT(4) // A floating point angle
#define DT_TIMEWINDOW_8 BIT(5) // A floating point timestamp relative to server time
#define DT_TIMEWINDOW_BIG BIT(6) // A floating point timestamp relative to server time (with more precision and custom multiplier)
#define DT_STRING BIT(7) // A null terminated string, sent as 8 byte chars
#define DT_SIGNED BIT(31) // sign modificator
#define FDT_MARK BIT(0) // Delta mark for sending
/* <23bb1> ../engine/delta.c:47 */
typedef struct delta_link_s
{
@ -520,6 +507,15 @@ void DELTA_MarkSendFields(unsigned char *from, unsigned char *to, delta_t *pFiel
if (*(uint32 *)&from[pTest->fieldOffset] != *(uint32 *)&to[pTest->fieldOffset])
pTest->flags |= FDT_MARK;
break;
// don't use multiplier when checking, to increase performance
#ifdef REHLDS_FIXES
case DT_TIMEWINDOW_8:
case DT_TIMEWINDOW_BIG:
if (*(uint32 *)&from[pTest->fieldOffset] != *(uint32 *)&to[pTest->fieldOffset])
pTest->flags |= FDT_MARK;
break;
#else
case DT_TIMEWINDOW_8:
if ((int32)(*(float *)&from[pTest->fieldOffset] * 100.0) != (int32)(*(float *)&to[pTest->fieldOffset] * 100.0))
pTest->flags |= FDT_MARK;
@ -528,6 +524,7 @@ void DELTA_MarkSendFields(unsigned char *from, unsigned char *to, delta_t *pFiel
if ((int32)(*(float *)&from[pTest->fieldOffset] * 1000.0) != (int32)(*(float *)&to[pTest->fieldOffset] * 1000.0))
pTest->flags |= FDT_MARK;
break;
#endif
case DT_STRING:
st1 = (char*)&from[pTest->fieldOffset];
st2 = (char*)&to[pTest->fieldOffset];
@ -691,12 +688,19 @@ int DELTA_CheckDelta(unsigned char *from, unsigned char *to, delta_t *pFields)
}
/* <247f5> ../engine/delta.c:949 */
int DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void))
NOINLINE int DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void))
{
int sendfields;
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
DELTAJit_ClearAndMarkSendFields(from, to, pFields);
#else
DELTA_ClearFlags(pFields);
DELTA_MarkSendFields(from, to, pFields);
#endif
sendfields = DELTA_CountSendFields(pFields);
_DELTA_WriteDelta(from, to, force, pFields, callback, sendfields);
return sendfields;
}

View File

@ -25,15 +25,22 @@
* version.
*
*/
#ifndef DELTA_H
#define DELTA_H
#ifdef _WIN32
#pragma once
#endif
#include "maintypes.h"
#define DT_BYTE BIT(0) // A byte
#define DT_SHORT BIT(1) // 2 byte field
#define DT_FLOAT BIT(2) // A floating point field
#define DT_INTEGER BIT(3) // 4 byte integer
#define DT_ANGLE BIT(4) // A floating point angle
#define DT_TIMEWINDOW_8 BIT(5) // A floating point timestamp relative to server time
#define DT_TIMEWINDOW_BIG BIT(6) // A floating point timestamp relative to server time (with more precision and custom multiplier)
#define DT_STRING BIT(7) // A null terminated string, sent as 8 byte chars
#define DT_SIGNED BIT(31) // sign modificator
#define FDT_MARK BIT(0) // Delta mark for sending
typedef struct delta_s delta_t;
@ -61,6 +68,8 @@ typedef struct delta_description_s
delta_stats_t stats;
} delta_description_t;
class CDeltaJit;
/* <bfa0> ../engine/delta.h:78 */
typedef struct delta_s
{
@ -69,6 +78,10 @@ typedef struct delta_s
char conditionalencodename[32];
encoder_t conditionalencode;
delta_description_t *pdd;
#ifdef REHLDS_FIXES
CDeltaJit* jit;
#endif
} delta_t;
/* <23b2a> ../engine/delta.h:104 */
@ -88,6 +101,14 @@ typedef struct delta_definition_list_s delta_definition_list_t;
typedef struct delta_registry_s delta_registry_t;
typedef struct delta_info_s delta_info_t;
/* <a59b9> ../engine/sv_main.c:102 */
typedef struct delta_info_s
{
delta_info_s *next;
char *name;
char *loadfile;
delta_t *delta;
} delta_info_t;
#ifdef HOOK_ENGINE
#define g_defs (*pg_defs)
@ -145,5 +166,3 @@ void DELTA_PrintStats(const char *name, delta_t *p);
void DELTA_DumpStats_f(void);
void DELTA_Init(void);
void DELTA_Shutdown(void);
#endif // DELTA_H

332
rehlds/engine/delta_jit.cpp Normal file
View File

@ -0,0 +1,332 @@
#include "precompiled.h"
#include "jitasm.h"
CDeltaJitRegistry g_DeltaJitRegistry;
uint32 DELTAJIT_CreateMask(int startBit, int endBit) {
if (startBit < 0) startBit = 0;
if (endBit < 0) endBit = 0;
if (startBit > 32) startBit = 32;
if (endBit > 32) endBit = 32;
uint32 res = 0xFFFFFFFF;
res &= (0xFFFFFFFF << startBit);
res &= (0xFFFFFFFF >> (32 - endBit));
return res;
}
unsigned int DELTAJIT_GetFieldSize(delta_description_t* desc) {
switch (desc->fieldType & ~DT_SIGNED) {
case DT_BYTE: return 1;
case DT_SHORT: return 2;
case DT_FLOAT:
case DT_INTEGER:
case DT_ANGLE:
case DT_TIMEWINDOW_8:
case DT_TIMEWINDOW_BIG:
return 4;
case DT_STRING:
return desc->fieldSize;
default:
rehlds_syserror("%s: Unknown delta field type %d", __FUNCTION__, desc->fieldType);
return 0;
}
}
void DELTAJIT_CreateDescription(delta_t* delta, deltajitdata_t &jitdesc) {
//calculate max offset and number of memblocks
unsigned int maxOffset = 0;
for (int i = 0; i < delta->fieldCount; i++) {
delta_description_t* desc = &delta->pdd[i];
unsigned fieldMaxOff = DELTAJIT_GetFieldSize(desc);
fieldMaxOff += desc->fieldOffset;
if (fieldMaxOff > maxOffset) {
maxOffset = fieldMaxOff;
}
}
unsigned int numMemBlocks = maxOffset / 16;
if (maxOffset % 16 || numMemBlocks == 0) {
numMemBlocks++;
}
//sanity checks & pre-clean
if (numMemBlocks >= DELTAJIT_MAX_BLOCKS) {
rehlds_syserror("%s: numMemBlocks >= DELTAJIT_MAX_BLOCKS (%d >= %d)", __FUNCTION__, numMemBlocks, DELTAJIT_MAX_BLOCKS);
return;
}
if (delta->fieldCount >= DELTAJIT_MAX_FIELDS) {
rehlds_syserror("%s: fieldCount >= DELTAJIT_MAX_FIELDS (%d >= %d)", __FUNCTION__, delta->fieldCount, DELTAJIT_MAX_FIELDS);
return;
}
memset(&jitdesc, 0, sizeof(jitdesc));
jitdesc.numblocks = numMemBlocks;
jitdesc.numFields = delta->fieldCount;
//create descriptions (primitive types)
for (int i = 0; i < delta->fieldCount; i++) {
delta_description_t* fieldDesc = &delta->pdd[i];
unsigned int blockId = fieldDesc->fieldOffset / 16;
unsigned int blockStart = blockId * 16;
unsigned int fieldSize = DELTAJIT_GetFieldSize(fieldDesc);
auto jitField = &jitdesc.fields[i];
jitField->id = i;
jitField->offset = fieldDesc->fieldOffset;
jitField->type = fieldDesc->fieldType;
jitField->length = fieldSize;
if (fieldDesc->fieldType != DT_STRING) {
bool firstBlock = true;
deltajit_memblock_field* blockField = NULL;
while (blockStart < fieldDesc->fieldOffset + fieldSize) {
deltajit_memblock* memblock = &jitdesc.blocks[blockId];
uint32 mask = DELTAJIT_CreateMask(fieldDesc->fieldOffset - blockStart, fieldDesc->fieldOffset + fieldSize - blockStart);
blockField = &memblock->fields[memblock->numFields++];
blockField->field = jitField;
jitField->numBlocks++;
blockField->first = firstBlock;
blockField->mask = mask;
blockStart += 16;
blockId++;
firstBlock = false;
}
blockField->last = true;
}
}
}
class CDeltaClearMarkFieldsJIT : public jitasm::function<void, CDeltaClearMarkFieldsJIT, void*, void*, void*> {
public:
deltajitdata_t *jitdesc;
CDeltaClearMarkFieldsJIT(deltajitdata_t *_jitdesc) : jitdesc(_jitdesc) {
}
void checkFieldMask(jitasm::Frontend::Reg32& mask, deltajit_memblock_field* jitField);
void main(Addr src, Addr dst, Addr fields);
void processStrings(Addr src, Addr dst, Addr fields);
};
void CDeltaClearMarkFieldsJIT::checkFieldMask(jitasm::Frontend::Reg32& mask, deltajit_memblock_field* jitField) {
test(mask, (uint16)jitField->mask);
setnz(al);
movzx(dx, al);
}
void CDeltaClearMarkFieldsJIT::main(Addr src, Addr dst, Addr fields)
{
#ifndef REHLDS_FIXES
sub(esp, 12); //some local storage is required for precise DT_TIMEWINDOW marking
#endif
mov(esi, ptr[src]);
mov(edi, ptr[dst]);
mov(ecx, ptr[fields]);
movdqu(xmm3, xmmword_ptr[esi]);
movdqu(xmm4, xmmword_ptr[edi]);
auto zero_xmm = xmm2;
pxor(zero_xmm, zero_xmm);
auto mask = ebx;
xor_(mask, mask);
for (unsigned int i = 0; i < jitdesc->numblocks; i++) {
movdqa(xmm0, xmm3);
movdqa(xmm1, xmm4);
//prefetch next blocks
if (i < jitdesc->numblocks) {
mov(esi, ptr[src]);
mov(edi, ptr[dst]);
movdqu(xmm3, xmmword_ptr[esi + ((i + 1) * 16)]);
movdqu(xmm4, xmmword_ptr[edi + ((i + 1) * 16)]);
}
pxor(xmm0, xmm1);
pcmpeqb(xmm0, xmm2);
pmovmskb(mask, xmm0);
not_(mask);
auto block = &jitdesc->blocks[i];
for (unsigned int j = 0; j < block->numFields; j++) {
auto jitField = &block->fields[j];
#ifndef REHLDS_FIXES
if (jitField->field->type == DT_TIMEWINDOW_8 || jitField->field->type == DT_TIMEWINDOW_BIG) {
if (jitField->last) {
float multiplier = (jitField->field->type == DT_TIMEWINDOW_8) ? 100.0f : 1000.0f;
uint32 m32 = *(uint32*)(&multiplier);
mov(dword_ptr[esp], m32);
fld(dword_ptr[esi + jitField->field->offset]);
fld(dword_ptr[esp]);
fmulp();
fstp(qword_ptr[esp + 4]);
cvttsd2si(eax, mmword_ptr[esp + 4]);
fld(dword_ptr[edi + jitField->field->offset]);
fld(dword_ptr[esp]);
fmulp();
fstp(qword_ptr[esp + 4]);
cvttsd2si(edx, mmword_ptr[esp + 4]);
cmp(eax, edx);
setne(al);
movzx(dx, al);
} else {
continue;
}
} else {
checkFieldMask(mask, jitField);
}
#else
checkFieldMask(mask, jitField);
#endif
int flagsOffset = (jitField->field->id * sizeof(delta_description_t) + offsetof(delta_description_t, flags));
if (jitField->first) {
mov(word_ptr[ecx + flagsOffset], dx);
}
else {
or_(word_ptr[ecx + flagsOffset], dx);
}
}
}
processStrings(src, dst, fields);
#ifndef REHLDS_FIXES
add(esp, 12); //some local storage is required for precise DT_TIMEWINDOW marking
#endif
}
void CDeltaClearMarkFieldsJIT::processStrings(Addr src, Addr dst, Addr fields) {
//strings
for (unsigned int i = 0; i < jitdesc->numFields; i++) {
auto jitField = &jitdesc->fields[i];
if (jitField->type != DT_STRING)
continue;
mov(esi, ptr[src]);
mov(edi, ptr[dst]);
add(esi, jitField->offset);
add(edi, jitField->offset);
push(esi);
push(edi);
mov(ecx, (size_t)&Q_stricmp);
call(ecx);
add(esp, 8);
test(eax, eax);
setnz(cl);
movzx(cx, cl);
mov(edx, ptr[fields]);
int flagsOffset = (jitField->id * sizeof(delta_description_t) + offsetof(delta_description_t, flags));
mov(word_ptr[edx + flagsOffset], cx);
}
}
class CDeltaJit {
public:
CDeltaClearMarkFieldsJIT* cleanMarkCheckFunc;
delta_t* delta;
CDeltaJit(delta_t* _delta, CDeltaClearMarkFieldsJIT* _cleanMarkCheckFunc) {
delta = _delta;
cleanMarkCheckFunc = _cleanMarkCheckFunc;
}
virtual ~CDeltaJit() {
if (cleanMarkCheckFunc) {
delete cleanMarkCheckFunc;
cleanMarkCheckFunc = NULL;
}
}
};
CDeltaJitRegistry::CDeltaJitRegistry() {
}
void CDeltaJitRegistry::RegisterDeltaJit(delta_t* delta, CDeltaJit* deltaJit) {
void* key = delta;
#ifndef REHLDS_FIXES
m_DeltaToJITMap.put(key, deltaJit);
#else
delta->jit = deltaJit;
#endif
}
CDeltaJit* CDeltaJitRegistry::GetJITByDelta(delta_t* delta) {
#ifndef REHLDS_FIXES
void* key = delta;
auto node = m_DeltaToJITMap.get(key);
return (node != NULL) ? node->val : NULL;
#else
return delta->jit;
#endif
}
void CDeltaJitRegistry::CreateAndRegisterDeltaJIT(delta_t* delta) {
deltajitdata_t data;
DELTAJIT_CreateDescription(delta, data);
CDeltaClearMarkFieldsJIT* cleanMarkCheckFunc = new CDeltaClearMarkFieldsJIT(&data);
cleanMarkCheckFunc->Assemble();
cleanMarkCheckFunc->jitdesc = NULL;
CDeltaJit* deltaJit = new CDeltaJit(delta, cleanMarkCheckFunc);
RegisterDeltaJit(delta, deltaJit);
}
NOINLINE void DELTAJit_ClearAndMarkSendFields(unsigned char *from, unsigned char *to, delta_t *pFields) {
CDeltaJit* deltaJit = g_DeltaJitRegistry.GetJITByDelta(pFields);
if (!deltaJit) {
rehlds_syserror("%s: JITted delta encoder not found for delta %p", __FUNCTION__, pFields);
return;
}
CDeltaClearMarkFieldsJIT &func = *deltaJit->cleanMarkCheckFunc;
func(from, to, pFields->pdd);
if (pFields->conditionalencode)
pFields->conditionalencode(pFields, from, to);
}
void CDeltaJitRegistry::Cleanup() {
#ifndef REHLDS_FIXES
for (auto itr = m_DeltaToJITMap.iterator(); itr.hasElement(); itr.next()) {
auto node = itr.current();
CDeltaJit* deltaJit = node->val;
delete deltaJit;
}
m_DeltaToJITMap.clear();
#else
delta_info_t* cur = g_sv_delta;
while (cur) {
delete cur->delta->jit;
cur->delta->jit = NULL;
cur = cur->next;
}
#endif
}

54
rehlds/engine/delta_jit.h Normal file
View File

@ -0,0 +1,54 @@
#pragma once
#include "maintypes.h"
#define DELTAJIT_MAX_BLOCKS 32
#define DELTAJIT_MAX_FIELDS 96
struct deltajit_field {
unsigned int id;
unsigned int offset;
unsigned int length;
int type;
unsigned int numBlocks;
};
struct deltajit_memblock_field {
deltajit_field* field;
uint16 mask;
bool first;
bool last;
};
struct deltajit_memblock {
unsigned int numFields;
deltajit_memblock_field fields[24];
};
struct deltajitdata_t {
unsigned int numblocks;
deltajit_memblock blocks[DELTAJIT_MAX_BLOCKS];
unsigned int numFields;
deltajit_field fields[DELTAJIT_MAX_FIELDS];
};
class CDeltaJit;
class CDeltaJitRegistry {
private:
#ifndef REHLDS_FIXES
CStaticMap<void*, CDeltaJit*, 4, 64> m_DeltaToJITMap;
#endif
public:
CDeltaJitRegistry();
void RegisterDeltaJit(delta_t* delta, CDeltaJit* deltaJit);
CDeltaJit* GetJITByDelta(delta_t* delta);
void CreateAndRegisterDeltaJIT(delta_t* delta);
void Cleanup();
};
extern CDeltaJitRegistry g_DeltaJitRegistry;
extern void DELTAJit_ClearAndMarkSendFields(unsigned char *from, unsigned char *to, delta_t *pFields);

View File

@ -28,12 +28,6 @@
#include "precompiled.h"
#ifdef _WIN32
#define FILESYSTEM_DLL_NAME "filesystem_stdio.dll"
#else
#define FILESYSTEM_DLL_NAME "filesystem_stdio.so"
#endif
CUtlVector<char *> g_fallbackLocalizationFiles;
char s_pBaseDir[512];
bool bLowViolenceBuild;

View File

@ -36,6 +36,12 @@
#include "iregistry.h"
#include "utlvector.h"
#ifdef _WIN32
#define FILESYSTEM_DLL_NAME "filesystem_stdio.dll"
#else
#define FILESYSTEM_DLL_NAME "filesystem_stdio.so"
#endif
#ifdef HOOK_ENGINE
#define g_fallbackLocalizationFiles (*pg_fallbackLocalizationFiles)
#define s_pBaseDir (*ps_pBaseDir)

View File

@ -28,12 +28,6 @@
#include "precompiled.h"
#define FILETIME_TO_QWORD(ft) \
((((uint64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime)
#define FILETIME_TO_PAIR(f,h)\
(((uint64)f << 32) | h)
/* <3d3ff> ../engine/host_cmd.c:4378 */
typedef int(*SV_BLENDING_INTERFACE_FUNC)(int, struct sv_blending_interface_s **, struct server_studio_api_s *, float *, float *);

View File

@ -36,6 +36,12 @@
#include "eiface.h"
#include "FileSystem.h"
#define FILETIME_TO_QWORD(ft) \
((((uint64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime)
#define FILETIME_TO_PAIR(f,h)\
(((uint64)f << 32) | h)
/* <3d22f> ../engine/host_cmd.c:83 */
typedef void (*SV_SAVEGAMECOMMENT_FUNC)(char *, int);

View File

@ -28,9 +28,6 @@
#include "precompiled.h"
#include <smmintrin.h>
#include <xmmintrin.h>
vec3_t vec3_origin;
//int nanmask;
//short int new_cw;

View File

@ -28,10 +28,6 @@
#include "precompiled.h"
// Create general message queues
#define NUM_MSG_QUEUES 40
#define MSG_QUEUE_SIZE 1536
#ifdef _WIN32
CRITICAL_SECTION net_cs;
#endif // _WIN32

View File

@ -56,7 +56,9 @@
//1400 - 9 = 1391
#define SPLIT_SIZE (MAX_ROUTEABLE_PACKET - sizeof(SPLITPACKET))
// Create general message queues
#define NUM_MSG_QUEUES 40
#define MSG_QUEUE_SIZE 1536
/* <d297f> ../engine/net_ws.c:137 */
typedef struct loopmsg_s

View File

@ -28,9 +28,6 @@
#include "precompiled.h"
// 1/32 epsilon to keep floating point happy
#define DIST_EPSILON (0.03125f)
int g_contentsresult;
hull_t box_hull_0;
box_clipnodes_t box_clipnodes_0;
@ -645,6 +642,8 @@ qboolean PM_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, cons
float t2;
float midf;
float DIST_EPSILON = 0.03125f;
if (num < 0)
{
if (num == CONTENTS_SOLID)
@ -792,6 +791,8 @@ qboolean PM_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, cons
float midf;
vec3_t custom_p1; // for holding custom p1 value
float DIST_EPSILON = 0.03125f;
while (1)
{
if (num < 0)

View File

@ -139,7 +139,14 @@ void PF_setmodel_I(edict_t *e, const char *m)
for (; *check; i++, check++)
#endif
{
//use case-sensitive names to increase performance
#ifdef REHLDS_FIXES
if (!Q_strcmp(*check, m))
#else
if (!Q_stricmp(*check, m))
#endif
{
e->v.modelindex = i;
model_t *mod = g_psv.models[i];
@ -1423,14 +1430,25 @@ int PF_precache_model_I(const char *s)
#else
g_psv.model_precache[i] = s;
#endif // REHLDS_FIXES
#ifdef REHLDS_OPT_PEDANTIC
g_rehlds_sv.modelsMap.put(g_psv.model_precache[i], i);
#endif //REHLDS_OPT_PEDANTIC
g_psv.models[i] = Mod_ForName(s, 1, 1);
if (!iOptional)
g_psv.model_precache_flags[i] |= 1u;
return i;
}
//use case-sensitive names to increase performance
#ifdef REHLDS_FIXES
if (!Q_strcmp(g_psv.model_precache[i], s))
return i;
#else
if (!Q_stricmp(g_psv.model_precache[i], s))
return i;
#endif
}
Host_Error(
"PF_precache_model_I: Model '%s' failed to precache because the item count is over the %d limit.\nReduce the number of brush models and/or regular models in the map to correct this.",
@ -1441,8 +1459,14 @@ int PF_precache_model_I(const char *s)
{
for (int i = 0; i < HL_MODEL_MAX; i++)
{
//use case-sensitive names to increase performance
#ifdef REHLDS_FIXES
if (!Q_strcmp(g_psv.model_precache[i], s))
return i;
#else
if (!Q_stricmp(g_psv.model_precache[i], s))
return i;
#endif
}
Host_Error("PF_precache_model_I: '%s' Precache can only be done in spawn functions", s);
}

View File

@ -164,6 +164,19 @@ typedef struct server_s
unsigned char signon_data[32768];
} server_t;
struct rehlds_server_t {
//map for sv.model_precache (for faster resolving of model index by its name)
#if defined(REHLDS_FIXES)
CStringKeyStaticMap<int, 7, HL_MODEL_MAX * 2> modelsMap; //case-sensitive keys for better performance
#elif defined(REHLDS_OPT_PEDANTIC)
CICaseStringKeyStaticMap<int, 7, HL_MODEL_MAX * 2> modelsMap; //use case-insensitive keys to conform original engine's behavior
#endif
};
/* <3b30a> ../engine/server.h:163 */
typedef struct client_frame_s
{
@ -430,6 +443,8 @@ extern globalvars_t gGlobalVariables;
extern server_static_t g_psvs;
extern server_t g_psv;
extern rehlds_server_t g_rehlds_sv;
extern cvar_t sv_lan;
extern cvar_t sv_lan_rate;
extern cvar_t sv_aim;

View File

@ -35,16 +35,6 @@ typedef struct full_packet_entities_s
entity_state_t entities[MAX_PACKET_ENTITIES];
} full_packet_entities_t;
/* <a59b9> ../engine/sv_main.c:102 */
typedef struct delta_info_s
{
delta_info_s *next;
char *name;
char *loadfile;
delta_t *delta;
} delta_info_t;
int sv_lastnum;
extra_baselines_t g_sv_instance_baselines;
@ -66,6 +56,8 @@ globalvars_t gGlobalVariables;
server_static_t g_psvs;
server_t g_psv;
rehlds_server_t g_rehlds_sv;
decalname_t sv_decalnames[512];
int sv_decalnamecount;
@ -695,8 +687,15 @@ void SV_FindModelNumbers(void)
{
if (!g_psv.model_precache[i])
break;
//use case-sensitive names to increase performance
#ifdef REHLDS_FIXES
if (!Q_stricmp(g_psv.model_precache[i], "models/player.mdl"))
sv_playermodel = i;
#else
if (!Q_stricmp(g_psv.model_precache[i], "models/player.mdl"))
sv_playermodel = i;
#endif
}
}
@ -4853,6 +4852,12 @@ int SV_ModelIndex(const char *name)
if (!name || !name[0])
return 0;
#ifdef REHLDS_OPT_PEDANTIC
auto node = g_rehlds_sv.modelsMap.get(name);
if (node) {
return node->val;
}
#else
for (int i = 0; i < HL_MODEL_MAX; i++)
{
if (!g_psv.model_precache[i])
@ -4861,6 +4866,7 @@ int SV_ModelIndex(const char *name)
if (!Q_stricmp(g_psv.model_precache[i], name))
return i;
};
#endif
Sys_Error("SV_ModelIndex: model %s not precached", name);
}
@ -5465,6 +5471,11 @@ int SV_SpawnServer(qboolean bIsDemo, char *server, char *startspot)
SV_AllocClientFrames();
Q_memset(&g_psv, 0, sizeof(server_t));
#ifdef REHLDS_OPT_PEDANTIC
g_rehlds_sv.modelsMap.clear();
#endif
Q_strncpy(g_psv.oldname, oldname, sizeof(oldname) - 1);
g_psv.oldname[sizeof(oldname) - 1] = 0;
Q_strncpy(g_psv.name, server, sizeof(g_psv.name) - 1);
@ -5577,6 +5588,13 @@ int SV_SpawnServer(qboolean bIsDemo, char *server, char *startspot)
g_psv.model_precache_flags[1] |= RES_FATALIFMISSING;
g_psv.model_precache[1] = g_psv.modelname;
#ifdef REHLDS_OPT_PEDANTIC
{
int __itmp = 1;
g_rehlds_sv.modelsMap.put(ED_NewString(g_psv.modelname), __itmp);
}
#endif
g_psv.sound_precache[0] = pr_strings;
g_psv.model_precache[0] = pr_strings;
g_psv.generic_precache[0] = pr_strings;
@ -5586,6 +5604,13 @@ int SV_SpawnServer(qboolean bIsDemo, char *server, char *startspot)
g_psv.model_precache[i + 1] = localmodels[i];
g_psv.models[i + 1] = Mod_ForName(localmodels[i], FALSE, FALSE);
g_psv.model_precache_flags[i + 1] |= RES_FATALIFMISSING;
#ifdef REHLDS_OPT_PEDANTIC
{
int __itmp = i + 1;
g_rehlds_sv.modelsMap.put(g_psv.model_precache[i + 1], __itmp);
}
#endif
}
Q_memset(&g_psv.edicts->v, 0, sizeof(entvars_t));
@ -6789,6 +6814,10 @@ void SV_RegisterDelta(char *name, char *loadfile)
p->delta = pdesc;
p->next = g_sv_delta;
g_sv_delta = p;
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
g_DeltaJitRegistry.CreateAndRegisterDeltaJIT(pdesc);
#endif
}
/* <aa966> ../engine/sv_main.c:9284 */
@ -6826,6 +6855,10 @@ void SV_InitDeltas(void)
g_peventdelta = SV_LookupDelta("event_t");
if (!g_peventdelta)
Sys_Error("No event_t encoder on server!\n");
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
g_DeltaJitRegistry.CreateAndRegisterDeltaJIT(&g_MetaDelta[0]);
#endif
}
/* <aac49> ../engine/sv_main.c:9339 */
@ -7012,6 +7045,7 @@ void SV_Init(void)
/* <aad4b> ../engine/sv_main.c:9558 */
void SV_Shutdown(void)
{
g_DeltaJitRegistry.Cleanup();
delta_info_t *p = g_sv_delta;
while (p)
{

View File

@ -28,8 +28,6 @@
#include "precompiled.h"
#define DI_NODIR -1
/*
* Local initialization
*/

View File

@ -35,6 +35,8 @@
#include "maintypes.h"
#include "server.h"
#define DI_NODIR -1
#ifdef HOOK_ENGINE
#define c_yes (*pc_yes)

View File

@ -222,7 +222,7 @@ void Sys_SetupFPUOptions()
__asm { fldenv byte ptr fpuOpts }
}
__declspec(noinline) void Sys_InitFPUControlWords()
NOINLINE void Sys_InitFPUControlWords()
{
int fpucw = 0;
__asm { fnstcw fpucw }
@ -280,13 +280,13 @@ void __cdecl Sys_InitHardwareTimer()
}
int g_SavedFPUCW1 = 0;
__declspec(noinline) void Sys_FPUCW_Push_Prec64() {
NOINLINE void Sys_FPUCW_Push_Prec64() {
uint16 tmp = g_FPUCW_Mask_Prec_64Bit;
__asm { fnstcw g_SavedFPUCW1 }
__asm { fldcw tmp }
}
__declspec(noinline) void Sys_FPUCW_Pop_Prec64() {
NOINLINE void Sys_FPUCW_Pop_Prec64() {
uint16 tmp = g_SavedFPUCW1;
__asm { fldcw tmp }
}

View File

@ -28,12 +28,6 @@
#include "precompiled.h"
#define FIFTEEN_MB (15 * 1024 * 1024)
#define MINIMUM_WIN_MEMORY 0x0e00000
#define WARNING_MEMORY 0x0200000
#define MAXIMUM_WIN_MEMORY 0x2800000 // Ask for 40 MB max
#define MAXIMUM_DEDICATED_MEMORY 0x2800000 // Ask for 40 MB max
IDedicatedExports *dedicated_;
qboolean g_bIsWin95;
qboolean g_bIsWin98;

View File

@ -40,6 +40,12 @@
#include "engine_launcher_api.h"
#include "idedicatedexports.h"
#define FIFTEEN_MB (15 * 1024 * 1024)
#define MINIMUM_WIN_MEMORY 0x0e00000
#define WARNING_MEMORY 0x0200000
#define MAXIMUM_WIN_MEMORY 0x2800000 // Ask for 40 MB max
#define MAXIMUM_DEDICATED_MEMORY 0x2800000 // Ask for 40 MB max
#ifdef HOOK_ENGINE
#define dedicated_ (*pdedicated)
#define g_bIsWin95 (*pg_bIsWin95)

View File

@ -28,10 +28,6 @@
#include "precompiled.h"
// sleep time when not focus
#define NOT_FOCUS_SLEEP 50
#define MINIMIZED_SLEEP 20
/*
* Globals initialization
*/

View File

@ -33,6 +33,10 @@
#include "igame.h"
#include "iengine.h"
// sleep time when not focus
#define NOT_FOCUS_SLEEP 50
#define MINIMIZED_SLEEP 20
#ifdef HOOK_ENGINE
#define game (*pgame)
#define eng (*peng)

View File

@ -28,12 +28,6 @@
#include "precompiled.h"
#define MSGFILE_NAME 0
#define MSGFILE_TEXT 1
#define NAME_HEAP_SIZE 16384
#define MAX_MESSAGES 1000
char gNetworkTextMessageBuffer[MAX_NETMESSAGE][512];
client_textmessage_t gMessageParms;

View File

@ -42,6 +42,12 @@
#define MAX_NETMESSAGE 4
#define MSGFILE_NAME 0
#define MSGFILE_TEXT 1
#define NAME_HEAP_SIZE 16384
#define MAX_MESSAGES 1000
#ifdef HOOK_ENGINE
#define gMessageTable (*pgMessageTable)

View File

@ -485,4 +485,4 @@ qboolean Q_StripUnprintableAndSpace(char *pch)
free(pwch_alloced);
return bStrippedAny;
}
}

View File

@ -28,8 +28,6 @@
#include "precompiled.h"
#define DIST_EPSILON (0.03125f)
hull_t box_hull;
hull_t beam_hull;
box_clipnodes_t box_clipnodes;
@ -656,6 +654,8 @@ qboolean SV_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, cons
float midf;
float pdif = p2f - p1f;
float DIST_EPSILON = 0.03125f;
if (num >= 0)
{
if (num < hull->firstclipnode || num > hull->lastclipnode || !hull->planes)
@ -792,6 +792,8 @@ qboolean SV_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, cons
float pdif;
vec3_t custom_p1; // for holding custom p1 value
float DIST_EPSILON = 0.03125f;
while (num >= 0)
{
pdif = p2f - p1f;

View File

@ -30,6 +30,7 @@
#include "keys.h"
#include "decal.h"
#include "delta.h"
#include "delta_jit.h"
#include "server.h"
#include "sys_dll.h"
#include "sys_dll2.h"
@ -64,9 +65,6 @@
#include "net_ws.h"
#include "net_chan.h"
#include "tmessage.h"
#include "traceinit.h"
#include "wad.h"

View File

@ -43,6 +43,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
return (FALSE);
TestSuite_Init(NULL, &hlds_exe, NULL);
Rehlds_Debug_Init(NULL);
#endif
}

View File

@ -554,6 +554,22 @@ void Rehlds_Debug_logFree(void* ptr)
g_RehldsDebugLog.flush();
}
void Rehlds_Debug_LogDeltaFlags(delta_t* delta, int counter, bool verbose) {
unsigned int cksum = 0;
for (int i = 0; i < delta->fieldCount; i++) {
cksum = _mm_crc32_u16(cksum, delta->pdd[i].flags);
}
g_RehldsDebugLog << "DF(c=" << counter << " crc=" << cksum << ")\n";
if (verbose) {
for (int i = 0; i < delta->fieldCount; i++) {
g_RehldsDebugLog << "DeltaFlagsVerbose(counter=" << counter << " id=" << delta->pdd[i].fieldName << " flags= " << delta->pdd[i].flags << ")\n";
}
}
g_RehldsDebugLog.flush();
}
void Rehlds_Debug_Init(Module* engine)
{

View File

@ -41,6 +41,8 @@ extern void Rehlds_Debug_logAlloc(size_t sz, void* ptr);
extern void Rehlds_Debug_logRealloc(size_t sz, void* oldPtr, void* newPtr);
extern void Rehlds_Debug_logFree(void* ptr);
extern void Rehlds_Debug_LogDeltaFlags(delta_t* delta, int counter, bool verbose);
extern void Rehlds_Debug_Init(Module* engine);
#endif

View File

@ -53,6 +53,7 @@
<ClCompile Include="..\engine\cvar.cpp" />
<ClCompile Include="..\engine\decals.cpp" />
<ClCompile Include="..\engine\delta.cpp" />
<ClCompile Include="..\engine\delta_jit.cpp" />
<ClCompile Include="..\engine\ed_strpool.cpp" />
<ClCompile Include="..\engine\filesystem.cpp" />
<ClCompile Include="..\engine\filesystem_internal.cpp" />
@ -229,37 +230,53 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\unittests\mathlib_tests.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Record|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds Play|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\unittests\struct_offsets_tests.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Record|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Tests|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Test Fixes|Win32'">false</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\unittests\TestRunner.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">true</ExcludedFromBuild>
<ClCompile Include="..\unittests\delta_tests.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Record|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\unittests\tmessage_tests.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\unittests\mathlib_tests.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Record|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\unittests\struct_offsets_tests.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Record|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\unittests\TestRunner.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Record|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\unittests\tmessage_tests.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Record|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">true</ExcludedFromBuild>
</ClCompile>
@ -358,6 +375,7 @@
<ClInclude Include="..\engine\cvar.h" />
<ClInclude Include="..\engine\decal.h" />
<ClInclude Include="..\engine\delta.h" />
<ClInclude Include="..\engine\delta_jit.h" />
<ClInclude Include="..\engine\delta_packet.h" />
<ClInclude Include="..\engine\ed_strpool.h" />
<ClInclude Include="..\engine\event.h" />
@ -709,7 +727,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>REHLDS_OPT_PEDANTIC;REHLDS_SELF;REHLDS_FIXES;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>REHLDS_OPT_PEDANTIC;REHLDS_SELF;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FloatingPointModel>Precise</FloatingPointModel>
<AdditionalOptions>/arch:IA32 %(AdditionalOptions)</AdditionalOptions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -861,6 +879,7 @@
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>

View File

@ -325,6 +325,12 @@
<ClCompile Include="..\unittests\mathlib_tests.cpp">
<Filter>unittests</Filter>
</ClCompile>
<ClCompile Include="..\engine\delta_jit.cpp">
<Filter>engine</Filter>
</ClCompile>
<ClCompile Include="..\unittests\delta_tests.cpp">
<Filter>unittests</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\hookers\memory.h">
@ -1032,6 +1038,9 @@
<ClInclude Include="..\public\rehlds\bspfile.h">
<Filter>public\rehlds</Filter>
</ClInclude>
<ClInclude Include="..\engine\delta_jit.h">
<Filter>engine</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\linux\appversion.sh">

View File

@ -131,3 +131,11 @@ uint32 crc32_t(uint32 iCRC, const uint8 *s, unsigned int len) {
uint32 crc32(const uint8 *buf, unsigned int len) {
return crc32_t(0, buf, len);
}
uint32 crc32_t8_sse(uint32 iCRC, uint8 data) {
return _mm_crc32_u8(iCRC, data);
}
uint32 crc32_t8_nosse(uint32 iCRC, uint8 data) {
return crc32_tab[(iCRC ^ data) & 0xff] ^ (iCRC >> 8);
}

View File

@ -18,4 +18,6 @@
uint32 crc32(const uint8 *buf, unsigned int len);
uint32 crc32_t(uint32 iCRC, const uint8 *s, unsigned int len);
uint32 crc32_t8_sse(uint32 iCRC, uint8 data);
uint32 crc32_t8_nosse(uint32 iCRC, uint8 data);

View File

@ -43,6 +43,9 @@
#include <setjmp.h>
#include <assert.h>
#include <algorithm>
#include <deque>
#ifdef _WIN32 // WINDOWS
#include <windows.h>
#include <winsock.h>
@ -85,6 +88,9 @@
#include <fstream>
#include <iomanip>
#include <smmintrin.h>
#include <xmmintrin.h>
#ifdef _WIN32 // WINDOWS
#define _CRT_SECURE_NO_WARNINGS
#define WIN32_LEAN_AND_MEAN

View File

@ -202,3 +202,56 @@ public:
return Iterator(this);
}
};
template<typename T_VAL, unsigned int ASSOC_2N, unsigned int MAX_VALS>
class CStringKeyStaticMap : public CStaticMap<const char*, T_VAL, ASSOC_2N, MAX_VALS> {
protected:
virtual uint32 hash(const char* const &val) {
return crc32((const unsigned char*)val, strlen(val));
}
virtual bool equals(const char* const &val1, const char* const &val2) {
return !strcmp(val1, val2);
}
public:
CStringKeyStaticMap() {
}
};
template<typename T_VAL, unsigned int ASSOC_2N, unsigned int MAX_VALS>
class CICaseStringKeyStaticMap : public CStaticMap<const char*, T_VAL, ASSOC_2N, MAX_VALS> {
protected:
virtual uint32 hash(const char* const &val) {
uint32 cksum = 0;
const char* pcc = val;
if (cpuinfo.sse4_2) {
while (*pcc) {
char cc = *(pcc++);
if (cc >= 'A' || cc <= 'Z') {
cc |= 0x20;
}
cksum = crc32_t8_sse(cksum, cc);
}
} else {
while (*pcc) {
char cc = *(pcc++);
if (cc >= 'A' || cc <= 'Z') {
cc |= 0x20;
}
cksum = crc32_t8_nosse(cksum, cc);
}
}
return cksum;
}
virtual bool equals(const char* const &val1, const char* const &val2) {
return !_stricmp(val1, val2);
}
public:
CICaseStringKeyStaticMap() {
}
};

8967
rehlds/rehlds/jitasm.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,362 @@
#include "precompiled.h"
#include "cppunitlite/TestHarness.h"
#pragma pack(push, 1)
struct delta_test_struct_t {
uint8 b_00; //0
uint8 b_01; //1
uint16 s_02; //2
uint32 i_04; //3
float f_08; //4
float w8_0C; //5
uint8 b_10; //6
uint8 b_11; //7
uint16 s_12; //8
uint32 i_14; //9
float f_18; //10
float w8_1C; //11
float wb_20; //12
char s_24[41]; //13
uint8 b_4D; //14
int i_4E; //15
uint8 b_52; //16
char s_53[9]; //17
uint8 b_5C; //18
int i_5D; //19
uint8 b_61; //20
};
#pragma pack(pop)
NOINLINE void _InitDeltaField(delta_description_t* fieldDesc, int expectedOffset, int type, const char* name, int off, short sz, int bits, float preMult, float postMult) {
if (expectedOffset != off) {
rehlds_syserror("%s: Expected and real offset mismatch (%d != %d)", expectedOffset, off);
}
fieldDesc->fieldType = type;
strcpy(fieldDesc->fieldName, name);
fieldDesc->fieldOffset = off;
fieldDesc->fieldSize = sz;
fieldDesc->significant_bits = bits;
fieldDesc->premultiply = preMult;
fieldDesc->postmultiply = postMult;
fieldDesc->flags = 0;
memset(&fieldDesc->stats, 0, sizeof(fieldDesc->stats));
}
NOINLINE void _FillTestDelta(delta_test_struct_t* data, char val) {
memset(data, val, sizeof(delta_test_struct_t));
data->s_24[ARRAYSIZE(data->s_24) - 1] = 0;
data->s_53[ARRAYSIZE(data->s_53) - 1] = 0;
data->w8_0C = (float)val;
data->w8_1C = (float)val;
data->wb_20 = (float)val;
}
NOINLINE void _DoMarkFields(void* src, void* dst, delta_t* delta, bool useJit) {
if (useJit) {
DELTAJit_ClearAndMarkSendFields((unsigned char*)src, (unsigned char*)dst, delta);
} else {
DELTA_ClearFlags(delta);
DELTA_MarkSendFields((unsigned char*)src, (unsigned char*)dst, delta);
}
}
NOINLINE void _EnsureFieldsChanged(const char* callsite, const char* action, bool changed, delta_t* delta, ...) {
va_list vargs;
va_start(vargs, delta);
const char* fieldName = va_arg(vargs, const char*);
while (fieldName) {
delta_description_t* field = NULL;
for (int i = 0; i < delta->fieldCount; i++) {
if (!strcmp(fieldName, delta->pdd[i].fieldName)) {
field = &delta->pdd[i];
break;
}
}
if (field == NULL) {
rehlds_syserror("%s: %s: Could not find delta field '%s'", callsite, action, fieldName);
}
if (field->flags & 0x80) {
rehlds_syserror("%s: %s: Field '%s' is marked as processed", callsite, action, fieldName);
}
if ((field->flags == 1) ^ changed) {
rehlds_syserror("%s: %s: Field '%s' is expected to be marked", callsite, action, fieldName);
}
field->flags |= 0x80;
fieldName = va_arg(vargs, const char*);
}
for (int i = 0; i < delta->fieldCount; i++) {
delta_description_t* field = &delta->pdd[i];
if (field->flags & 0x80)
continue;
if ((field->flags == 1) ^ !changed) {
rehlds_syserror("%s: %s: Field '%s' is expected to be unmarked", callsite, action, field->fieldName);
}
}
}
NOINLINE delta_t* _CreateTestDeltaDesc() {
delta_test_struct_t d;
static delta_description_t _fields[32];
_InitDeltaField(&_fields[0], 0x00, DT_BYTE, "b_00", offsetof(delta_test_struct_t, b_00), 1, 8, 1.0f, 1.0f);
_InitDeltaField(&_fields[1], 0x01, DT_BYTE, "b_01", offsetof(delta_test_struct_t, b_01), 1, 8, 1.0f, 1.0f);
_InitDeltaField(&_fields[2], 0x02, DT_SHORT, "s_02", offsetof(delta_test_struct_t, s_02), 2, 16, 1.0f, 1.0f);
_InitDeltaField(&_fields[3], 0x04, DT_INTEGER, "i_04", offsetof(delta_test_struct_t, i_04), 4, 32, 1.0f, 1.0f);
_InitDeltaField(&_fields[4], 0x08, DT_FLOAT, "f_08", offsetof(delta_test_struct_t, f_08), 4, 32, 1.0f, 1.0f);
_InitDeltaField(&_fields[5], 0x0C, DT_TIMEWINDOW_8, "w8_0C", offsetof(delta_test_struct_t, w8_0C), 4, 32, 1.0f, 1.0f);
_InitDeltaField(&_fields[6], 0x10, DT_BYTE, "b_10", offsetof(delta_test_struct_t, b_10), 1, 8, 1.0f, 1.0f);
_InitDeltaField(&_fields[7], 0x11, DT_BYTE, "b_11", offsetof(delta_test_struct_t, b_11), 1, 8, 1.0f, 1.0f);
_InitDeltaField(&_fields[8], 0x12, DT_SHORT, "s_12", offsetof(delta_test_struct_t, s_12), 2, 16, 1.0f, 1.0f);
_InitDeltaField(&_fields[9], 0x14, DT_INTEGER, "i_14", offsetof(delta_test_struct_t, i_14), 4, 32, 1.0f, 1.0f);
_InitDeltaField(&_fields[10], 0x18, DT_FLOAT, "f_18", offsetof(delta_test_struct_t, f_18), 4, 32, 1.0f, 1.0f);
_InitDeltaField(&_fields[11], 0x1C, DT_TIMEWINDOW_8, "w8_1C", offsetof(delta_test_struct_t, w8_1C), 4, 32, 1.0f, 1.0f);
_InitDeltaField(&_fields[12], 0x20, DT_TIMEWINDOW_BIG, "wb_20", offsetof(delta_test_struct_t, wb_20), 4, 32, 1.0f, 1.0f);
_InitDeltaField(&_fields[13], 0x24, DT_STRING, "s_24", offsetof(delta_test_struct_t, s_24), ARRAYSIZE(d.s_24), 0, 1.0f, 1.0f);
_InitDeltaField(&_fields[14], 0x4D, DT_BYTE, "b_4D", offsetof(delta_test_struct_t, b_4D), 1, 8, 1.0f, 1.0f);
_InitDeltaField(&_fields[15], 0x4E, DT_INTEGER, "i_4E", offsetof(delta_test_struct_t, i_4E), 4, 32, 1.0f, 1.0f);
_InitDeltaField(&_fields[16], 0x52, DT_BYTE, "b_52", offsetof(delta_test_struct_t, b_52), 1, 8, 1.0f, 1.0f);
_InitDeltaField(&_fields[17], 0x53, DT_STRING, "s_53", offsetof(delta_test_struct_t, s_53), ARRAYSIZE(d.s_53), 0, 1.0f, 1.0f);
_InitDeltaField(&_fields[18], 0x5C, DT_BYTE, "b_5C", offsetof(delta_test_struct_t, b_5C), 1, 8, 1.0f, 1.0f);
_InitDeltaField(&_fields[19], 0x5D, DT_INTEGER, "i_5D", offsetof(delta_test_struct_t, i_5D), 4, 32, 1.0f, 1.0f);
_InitDeltaField(&_fields[20], 0x61, DT_BYTE, "b_61", offsetof(delta_test_struct_t, b_61), 1, 8, 1.0f, 1.0f);
delta_t* delta = (delta_t*) Mem_ZeroMalloc(sizeof(delta_t));
delta->dynamic = false;
delta->fieldCount = 21;
delta->pdd = &_fields[0];
delta_info_t* dinfo = (delta_info_t*)Mem_ZeroMalloc(sizeof(delta_info_t));
dinfo->delta = delta;
dinfo->loadfile = Mem_Strdup("__fake_delta_test_struct_t");
dinfo->name = Mem_Strdup("delta_test_struct_t");
dinfo->next = g_sv_delta;
g_sv_delta = dinfo;
g_DeltaJitRegistry.CreateAndRegisterDeltaJIT(delta);
return delta;
};
TEST(MarkFieldsTest_Simple_Primitives, Delta, 1000) {
delta_t* delta = _CreateTestDeltaDesc();
delta_test_struct_t d1;
delta_test_struct_t d2;
for (int usejit = 0; usejit <= 1; usejit++) {
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "SimpleUnchangedAll", true, delta, NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x72);
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "SimpleUnchangedAll", false, delta, NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.b_01 = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Byte_0BlockCheck", true, delta, "b_01", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.b_11 = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Byte_1BlockCheck", true, delta, "b_11", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.s_02 = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Short_0BlockCheck", true, delta, "s_02", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.s_12 = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Short_1BlockCheck", true, delta, "s_12", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.i_04 = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Int_0BlockCheck", true, delta, "i_04", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.i_14 = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Int_1BlockCheck", true, delta, "i_14", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.f_08 = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Float_0BlockCheck", true, delta, "f_08", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.f_18 = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Float_0BlockCheck", true, delta, "f_18", NULL);
}
SV_Shutdown();
}
TEST(MarkFieldsTest_InterBlock, Delta, 1000) {
delta_t* delta = _CreateTestDeltaDesc();
delta_test_struct_t d1;
delta_test_struct_t d2;
for (int usejit = 0; usejit <= 1; usejit++) {
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.b_4D = d2.b_52 = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_guards", true, delta, "b_4D", "b_52", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.b_4D = d2.b_52 = 0;
d2.i_4E = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_guards_and_val", true, delta, "b_4D", "b_52", "i_4E", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.i_4E = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val", true, delta, "i_4E", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.i_4E &= 0xFFFFFF00;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_0b", true, delta, "i_4E", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.i_4E &= 0xFFFF00FF;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_1b", true, delta, "i_4E", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.i_4E &= 0xFF00FFFF;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_2b", true, delta, "i_4E", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.i_4E &= 0x00FFFFFF;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock1_val_3b", true, delta, "i_4E", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.b_5C = d2.b_61 = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_guards", true, delta, "b_5C", "b_61", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.b_5C = d2.b_61 = 0;
d2.i_5D = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_guards_and_val", true, delta, "b_5C", "b_61", "i_5D", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.i_5D = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val", true, delta, "i_5D", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.i_5D &= 0xFFFFFF00;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_0b", true, delta, "i_5D", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.i_5D &= 0xFFFF00FF;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_1b", true, delta, "i_5D", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.i_5D &= 0xFF00FFFF;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_2b", true, delta, "i_5D", NULL);
_FillTestDelta(&d1, 0x71); _FillTestDelta(&d2, 0x71);
d2.i_5D &= 0x00FFFFFF;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Interblock2_val_3b", true, delta, "i_5D", NULL);
}
SV_Shutdown();
}
TEST(MarkFieldsTest_Strings, Delta, 1000) {
delta_t* delta = _CreateTestDeltaDesc();
delta_test_struct_t d1;
delta_test_struct_t d2;
for (int usejit = 0; usejit <= 1; usejit++) {
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
d2.s_24[0] = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Str_empty", true, delta, "s_24", NULL);
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
d1.s_24[0] = 0;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Str_empty2", true, delta, "s_24", NULL);
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
d1.s_24[0] = d2.s_24[0] = 0;
d1.s_24[1] = 'd'; d2.s_24[1] = 'e';
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Str_both_empty_with_garbage", true, delta, NULL);
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
d1.s_24[1] = 'C';
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "Str_case_check", true, delta, NULL);
}
SV_Shutdown();
}
TEST(MarkFieldsTest_TimeWindow, Delta, 1000) {
#ifdef REHLDS_FIXES
bool rehds_fixes = true;
#else
bool rehds_fixes = false;
#endif
delta_t* delta = _CreateTestDeltaDesc();
delta_test_struct_t d1;
delta_test_struct_t d2;
for (int usejit = 0; usejit <= 1; usejit++) {
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
d2.w8_1C = 0.001f; d1.w8_1C = 0.0011f;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "TimeWindow_Below_Precision", true, delta, rehds_fixes ? "w8_1C" : NULL, NULL);
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
d2.w8_1C = 0.1f; d1.w8_1C = 0.11f; //precision check, 0.11f is actually 0.10999
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "TimeWindow_Above_Precision", true, delta, rehds_fixes ? "w8_1C" : NULL, NULL);
_FillTestDelta(&d1, 'c'); _FillTestDelta(&d2, 'c');
d2.w8_1C = 0.1f; d1.w8_1C = 0.12f;
_DoMarkFields(&d1, &d2, delta, usejit != 0);
_EnsureFieldsChanged(__FUNCTION__, "TimeWindow_Above_Precision", true, delta, "w8_1C", NULL);
}
SV_Shutdown();
}

View File

@ -92,25 +92,25 @@ TEST(AngleMatrixTest, MathLib, 1000) {
};
for (int sse = 0; sse <= 1; sse++) {
float rotationmatrix[3][4];
float rotation_matrix[3][4];
for (int i = 0; i < ARRAYSIZE(testdata); i++) {
AngleMatrix(testdata[i].angles, rotationmatrix);
AngleMatrix(testdata[i].angles, rotation_matrix);
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[0][0] mismatch", testdata[i].matrix0[0], rotation_matrix[0][0], 0.00001);
DOUBLES_EQUAL("rotationmatrix[0][1] mismatch", testdata[i].matrix0[1], rotation_matrix[0][1], 0.00001);
DOUBLES_EQUAL("rotationmatrix[0][2] mismatch", testdata[i].matrix0[2], rotation_matrix[0][2], 0.00001);
DOUBLES_EQUAL("rotationmatrix[0][3] mismatch", testdata[i].matrix0[3], rotation_matrix[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[1][0] mismatch", testdata[i].matrix1[0], rotation_matrix[1][0], 0.00001);
DOUBLES_EQUAL("rotationmatrix[1][1] mismatch", testdata[i].matrix1[1], rotation_matrix[1][1], 0.00001);
DOUBLES_EQUAL("rotationmatrix[1][2] mismatch", testdata[i].matrix1[2], rotation_matrix[1][2], 0.00001);
DOUBLES_EQUAL("rotationmatrix[1][3] mismatch", testdata[i].matrix1[3], rotation_matrix[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);
DOUBLES_EQUAL("rotationmatrix[2][0] mismatch", testdata[i].matrix2[0], rotation_matrix[2][0], 0.00001);
DOUBLES_EQUAL("rotationmatrix[2][1] mismatch", testdata[i].matrix2[1], rotation_matrix[2][1], 0.00001);
DOUBLES_EQUAL("rotationmatrix[2][2] mismatch", testdata[i].matrix2[2], rotation_matrix[2][2], 0.00001);
DOUBLES_EQUAL("rotationmatrix[2][3] mismatch", testdata[i].matrix2[3], rotation_matrix[2][3], 0.00001);
}
cpuinfo.sse4_1 = 0;
@ -128,15 +128,15 @@ TEST(DotProductTest, MathLib, 1000) {
};
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 },
{ { 41.5f, 7.32f, -9.22f }, { 13.3f, -0.5f, 8.09f }, 473.70020f },
{ { -16.1f, -0.09f, 1.2f }, { 8.2f, 1.2f, -6.66f }, -140.12000f },
};
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);
DOUBLES_EQUAL("_DotProduct mismatch", testdata[i].res, res, 0.0001);
}
cpuinfo.sse4_1 = 0;