2
0
mirror of https://github.com/rehlds/rehlds.git synced 2025-02-26 21:41:06 +03:00

Merge branch 'master' into flightrec

SSE4.2's crc32 is actually crc32c - removed crc32.*
This commit is contained in:
dreamstalker 2015-05-25 18:16:30 +04:00
commit 391bd5d627
58 changed files with 13473 additions and 2937 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

@ -2,3 +2,11 @@ apply plugin: 'java'
sourceCompatibility = '1.7'
targetCompatibility = '1.7'
repositories {
mavenCentral()
}
dependencies {
testCompile "junit:junit:4.12"
}

View File

@ -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

View File

@ -122,7 +122,7 @@ void setupToolchain(NativeBinarySpec b) {
}
b.lib LazyNativeDepSet.create(dep_bzip2, 'bzip2', b.buildType.name, true)
cfg.singleDefines 'USE_BREAKPAD_HANDLER', 'DEDICATED', 'SWDS', 'REHLDS_SELF', 'REHLDS_OPT_PEDANTIC'
cfg.singleDefines 'USE_BREAKPAD_HANDLER', 'DEDICATED', 'SWDS', 'REHLDS_SELF', 'REHLDS_OPT_PEDANTIC', 'REHLDS_FLIGHT_REC'
if (cfg instanceof MsvcToolchainConfig) {
cfg.compilerOptions.pchConfig = new MsvcToolchainConfig.PrecompiledHeadersConfig(
@ -184,7 +184,7 @@ class RehldsSrc {
include "**/*.cpp"
exclude "precompiled.cpp"
exclude GradleCppUtils.windows ? "tier0/platform_linux.cpp" : "tier0/platform_win32.cpp"
exclude "interface.cpp", "rehlds/crc32.cpp", "rehlds/sys_shared.cpp"
exclude "interface.cpp", "rehlds/crc32c.cpp", "rehlds/sys_shared.cpp"
}
source {
@ -321,10 +321,11 @@ model {
task buildRelease {
dependsOn binaries.withType(SharedLibraryBinarySpec).matching { SharedLibraryBinarySpec blib ->
blib.buildable && blib.buildType.name == 'release'
blib.buildable && blib.buildType.name == 'release' && !blib.name.contains('Rehlds_hooker_engine')
}
}
task prepareDevEnvTests {
def rehldsTests = new File(project.projectDir, '_dev/testDemos')

View File

@ -28,10 +28,6 @@
#include "precompiled.h"
char serverinfo[MAX_INFO_STRING];
char gpszVersionString[32];
@ -459,9 +455,29 @@ void MSG_WriteUsercmd(sizebuf_t *buf, usercmd_t *to, usercmd_t *from)
typedef struct bf_write_s
{
//For enhanced and safe bits writing functions
#if defined(REHLDS_FIXES)
#pragma pack(push, 1)
union {
uint64 u64;
uint32 u32[2];
uint8 u8[8];
} pendingData;
uint64 sse_highbits;
#pragma pack(pop)
int nCurOutputBit;
sizebuf_t *pbuf;
#else //defined(REHLDS_FIXES)
int nCurOutputBit;
unsigned char *pOutByte;
sizebuf_t *pbuf;
#endif //defined(REHLDS_FIXES)
} bf_write_t;
typedef struct bf_read_s
@ -476,7 +492,7 @@ typedef struct bf_read_s
// Bit field reading/writing storage.
bf_read_t bfread;
bf_write_t bfwrite;
ALIGN16 bf_write_t bfwrite;
void COM_BitOpsInit(void)
@ -485,6 +501,68 @@ void COM_BitOpsInit(void)
Q_memset(&bfread, 0, sizeof(bf_read_t));
}
//Enhanced and safe bits writing functions
#if defined(REHLDS_FIXES)
void MSG_WBits_MaybeFlush() {
if (bfwrite.nCurOutputBit < 32)
return;
uint32* pDest = (uint32*)SZ_GetSpace(bfwrite.pbuf, 4);
if (!(bfwrite.pbuf->flags & SIZEBUF_OVERFLOWED))
*pDest = bfwrite.pendingData.u32[0];
bfwrite.pendingData.u32[0] = bfwrite.pendingData.u32[1];
bfwrite.pendingData.u32[1] = 0;
bfwrite.nCurOutputBit -= 32;
}
void MSG_WriteBits(uint32 data, int numbits)
{
uint32 maxval = _mm_cvtsi128_si32(_mm_slli_epi64(_mm_cvtsi32_si128(1), numbits)) - 1; //maxval = (1 << numbits) - 1
if (data > maxval)
data = maxval;
MSG_WBits_MaybeFlush();
__m128i pending = _mm_load_si128((__m128i*) &bfwrite.pendingData.u64);
__m128i mmdata = _mm_slli_epi64(_mm_cvtsi32_si128(data), bfwrite.nCurOutputBit); //mmdata = data << bfwrite.nCurOutputBit
pending = _mm_or_si128(pending, mmdata);
_mm_store_si128((__m128i*) &bfwrite.pendingData.u64, pending);
bfwrite.nCurOutputBit += numbits;
}
void MSG_WriteOneBit(int nValue) {
MSG_WriteBits(nValue, 1);
}
void MSG_StartBitWriting(sizebuf_t *buf)
{
bfwrite.nCurOutputBit = 0;
bfwrite.pbuf = buf;
bfwrite.pendingData.u64 = 0;
}
void MSG_EndBitWriting(sizebuf_t *buf)
{
int bytesNeed = bfwrite.nCurOutputBit / 8;
if ((bfwrite.nCurOutputBit % 8) || bytesNeed == 0) {
bytesNeed++;
}
uint8* pData = (uint8*)SZ_GetSpace(bfwrite.pbuf, bytesNeed);
if (!(bfwrite.pbuf->flags & SIZEBUF_OVERFLOWED)) {
for (int i = 0; i < bytesNeed; i++) {
pData[i] = bfwrite.pendingData.u8[i];
}
}
}
#else // defined(REHLDS_FIXES)
void MSG_WriteOneBit(int nValue)
{
if (bfwrite.nCurOutputBit >= 8)
@ -516,13 +594,6 @@ void MSG_StartBitWriting(sizebuf_t *buf)
bfwrite.pOutByte = &buf->data[buf->cursize];
}
NOXREF qboolean MSG_IsBitWriting(void)
{
NOXREFCHECK;
return bfwrite.pbuf != 0;
}
void MSG_EndBitWriting(sizebuf_t *buf)
{
if (!(bfwrite.pbuf->flags & SIZEBUF_OVERFLOWED))
@ -582,6 +653,15 @@ void MSG_WriteBits(uint32 data, int numbits)
}
}
#endif //defined(REHLDS_FIXES)
NOXREF qboolean MSG_IsBitWriting(void)
{
NOXREFCHECK;
return bfwrite.pbuf != 0;
}
void MSG_WriteSBits(int data, int numbits)
{
int idata = data;
@ -1211,6 +1291,7 @@ void *SZ_GetSpace(sizebuf_t *buf, int length)
void *data;
const char *buffername = buf->buffername ? buf->buffername : "???";
if (length < 0)
{
Sys_Error(__FUNCTION__ ": %i negative length on %s", length, buffername);

View File

@ -526,7 +526,10 @@ void Cmd_CvarListPrintCvar(cvar_t *var, FileHandle_t f)
{
char szOutstr[256];
// TODO: Do correct output of string valued cvars
#ifdef REHLDS_FIXES
// Do correct output of string valued cvars
Q_snprintf(szOutstr, ARRAYSIZE(szOutstr) - 1, "%-28s : %16s", var->name, var->string);
#else // REHLDS_FIXES
if (var->value == (float)(int)var->value)
{
Q_snprintf(szOutstr, ARRAYSIZE(szOutstr) - 1, "%-15s : %8i", var->name, (int)var->value);
@ -535,6 +538,7 @@ void Cmd_CvarListPrintCvar(cvar_t *var, FileHandle_t f)
{
Q_snprintf(szOutstr, ARRAYSIZE(szOutstr) - 1, "%-15s : %8.3f", var->name, var->value);
}
#endif // REHLDS_FIXES
szOutstr[ARRAYSIZE(szOutstr) - 1] = 0;
if (var->flags & FCVAR_ARCHIVE)

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
{
@ -362,41 +349,63 @@ int DELTA_FindFieldIndex(struct delta_s *pFields, const char *fieldname)
}
Con_Printf(__FUNCTION__ ": Warning, couldn't find %s\n", fieldname);
return NULL;
return -1;
}
/* <24032> ../engine/delta.c:393 */
void DELTA_SetField(struct delta_s *pFields, const char *fieldname)
{
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
int index = DELTA_FindFieldIndex(pFields, fieldname);
if (index != -1)
DELTA_SetFieldByIndex(pFields, index);
#else
delta_description_t *pTest = DELTA_FindField(pFields, fieldname);
if (pTest)
{
pTest->flags |= FDT_MARK;
}
#endif
}
/* <240b2> ../engine/delta.c:411 */
void DELTA_UnsetField(struct delta_s *pFields, const char *fieldname)
{
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
int index = DELTA_FindFieldIndex(pFields, fieldname);
if (index != -1)
DELTA_UnsetFieldByIndex(pFields, index);
#else
delta_description_t *pTest = DELTA_FindField(pFields, fieldname);
if (pTest)
{
pTest->flags &= ~FDT_MARK;
}
#endif
}
/* <24132> ../engine/delta.c:429 */
void DELTA_SetFieldByIndex(struct delta_s *pFields, int fieldNumber)
{
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
DELTAJit_SetFieldByIndex(pFields, fieldNumber);
#else
pFields->pdd[fieldNumber].flags |= FDT_MARK;
#endif
}
/* <2416a> ../engine/delta.c:441 */
void DELTA_UnsetFieldByIndex(struct delta_s *pFields, int fieldNumber)
{
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
DELTAJit_UnsetFieldByIndex(pFields, fieldNumber);
#else
pFields->pdd[fieldNumber].flags &= ~FDT_MARK;
#endif
}
/* <23cc4> ../engine/delta.c:453 */
@ -441,17 +450,28 @@ int DELTA_TestDelta(unsigned char *from, unsigned char *to, delta_t *pFields)
case DT_ANGLE:
different = *(uint32 *)&from[pTest->fieldOffset] != *(uint32 *)&to[pTest->fieldOffset];
break;
#ifdef REHLDS_FIXES
// don't use multiplier when checking, to increase performance
case DT_TIMEWINDOW_8:
case DT_TIMEWINDOW_BIG:
different = (int32)(*(float *)&from[pTest->fieldOffset]) != (int32)(*(float *)&to[pTest->fieldOffset]);
break;
#else
case DT_TIMEWINDOW_8:
different = (int32)(*(float *)&from[pTest->fieldOffset] * 100.0) != (int32)(*(float *)&to[pTest->fieldOffset] * 100.0);
break;
case DT_TIMEWINDOW_BIG:
different = (int32)(*(float *)&from[pTest->fieldOffset] * 1000.0) != (int32)(*(float *)&to[pTest->fieldOffset] * 1000.0);
break;
#endif
case DT_STRING:
st1 = (char*)&from[pTest->fieldOffset];
st2 = (char*)&to[pTest->fieldOffset];
if (!(!*st1 && !*st2 || *st1 && *st2 && !Q_stricmp(st1, st2))) // Not sure why it is case insensitive, but it looks so
{
#ifdef REHLDS_FIXES
different = TRUE;
#endif // REHLDS_FIXES
length = Q_strlen(st2);
}
break;
@ -520,6 +540,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 +557,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];
@ -549,26 +579,40 @@ void DELTA_SetSendFlagBits(delta_t *pFields, int *bits, int *bytecount)
delta_description_t *pTest;
int i;
int lastbit = -1;
int bitnumber;
int fieldCount = pFields->fieldCount;
Q_memset(bits, 0, 8);
lastbit = -1;
bitnumber = -1;
for (i = fieldCount - 1, pTest = &pFields->pdd[i]; i >= 0; i--, pTest--)
{
if (pTest->flags & FDT_MARK)
{
if (lastbit == -1)
bitnumber = i;
lastbit = i;
bits[i > 31 ? 1 : 0] |= 1 << (i & 0x1F);
lastbit = bitnumber;
}
}
#ifdef REHLDS_FIXES
// fix for bad bytecount when no fields are marked
if (lastbit == -1) {
*bytecount = 0;
return;
}
#endif
*bytecount = (lastbit >> 3) + 1;
}
qboolean DELTA_IsFieldMarked(delta_t* pFields, int fieldNumber)
{
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
return DELTAJit_IsFieldMarked(pFields, fieldNumber);
#else
return pFields->pdd[fieldNumber].flags & FDT_MARK;
#endif
}
/* <2456d> ../engine/delta.c:782 */
void DELTA_WriteMarkedFields(unsigned char *from, unsigned char *to, delta_t *pFields)
{
@ -582,8 +626,13 @@ void DELTA_WriteMarkedFields(unsigned char *from, unsigned char *to, delta_t *pF
for (i = 0, pTest = pFields->pdd; i < fieldCount; i++, pTest++)
{
#if defined (REHLDS_OPT_PEDANTIC) || defined (REHLDS_FIXES)
if (!DELTA_IsFieldMarked(pFields, i))
continue;
#else
if (!(pTest->flags & FDT_MARK))
continue;
#endif
fieldSign = pTest->fieldType & DT_SIGNED;
fieldType = pTest->fieldType & ~DT_SIGNED;
@ -681,36 +730,61 @@ void DELTA_WriteMarkedFields(unsigned char *from, unsigned char *to, delta_t *pF
}
/* <2467e> ../engine/delta.c:924 */
int DELTA_CheckDelta(unsigned char *from, unsigned char *to, delta_t *pFields)
qboolean DELTA_CheckDelta(unsigned char *from, unsigned char *to, delta_t *pFields)
{
int sendfields;
qboolean sendfields;
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
sendfields = DELTAJit_Fields_Clear_Mark_Check(from, to, pFields, NULL);
#else
DELTA_ClearFlags(pFields);
DELTA_MarkSendFields(from, to, pFields);
sendfields = DELTA_CountSendFields(pFields);
#endif
return sendfields;
}
/* <247f5> ../engine/delta.c:949 */
int DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void))
NOINLINE qboolean DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void))
{
int sendfields;
qboolean sendfields;
int bytecount;
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
sendfields = DELTAJit_Fields_Clear_Mark_Check(from, to, pFields, NULL);
#else // REHLDS_OPT_PEDANTIC || REHLDS_FIXES
DELTA_ClearFlags(pFields);
DELTA_MarkSendFields(from, to, pFields);
sendfields = DELTA_CountSendFields(pFields);
#endif // REHLDS_OPT_PEDANTIC || REHLDS_FIXES
_DELTA_WriteDelta(from, to, force, pFields, callback, sendfields);
return sendfields;
}
/* <24760> ../engine/delta.c:963 */
int _DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void), int sendfields)
#ifdef REHLDS_FIXES //Fix for https://github.com/dreamstalker/rehlds/issues/24
qboolean DELTA_WriteDeltaForceMask(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void), void* pForceMask) {
qboolean sendfields = DELTAJit_Fields_Clear_Mark_Check(from, to, pFields, pForceMask);
_DELTA_WriteDelta(from, to, force, pFields, callback, sendfields);
return sendfields;
}
#endif
qboolean _DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)( void ), qboolean sendfields)
{
int i;
int bytecount;
int bits[2]; // this is a limit with 64 fields max in delta
int bits[2];
if (sendfields || force)
{
#if defined(REHLDS_OPT_PEDANTIC) || defined(REHLDS_FIXES)
DELTAJit_SetSendFlagBits(pFields, bits, &bytecount);
#else
DELTA_SetSendFlagBits(pFields, bits, &bytecount);
#endif
if (callback)
callback();
@ -718,7 +792,7 @@ int _DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, de
MSG_WriteBits(bytecount, 3);
for (i = 0; i < bytecount; i++)
{
MSG_WriteBits(((byte*)bits)[i], 8);
MSG_WriteBits(( (byte*)bits )[i], 8);
}
DELTA_WriteMarkedFields(from, to, pFields);
@ -727,6 +801,7 @@ int _DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, de
return 1;
}
/* <24aa0> ../engine/delta.c:1010 */
int DELTA_ParseDelta(unsigned char *from, unsigned char *to, delta_t *pFields)
{
@ -1028,6 +1103,12 @@ delta_t *DELTA_BuildFromLinks(delta_link_t **pplinks)
DELTA_ReverseLinks(pplinks);
count = DELTA_CountLinks(*pplinks);
#ifdef REHLDS_FIXES
if (count > DELTA_MAX_FIELDS)
Sys_Error(__FUNCTION__ ": Too many fields in delta description %i (MAX %i)\n", count, DELTA_MAX_FIELDS);
#endif
pdesc = (delta_description_t *)Mem_ZeroMalloc(sizeof(delta_description_t) * count);
for (p = *pplinks, pcur = pdesc; p != NULL; p = p->next, pcur++)

View File

@ -25,15 +25,24 @@
* version.
*
*/
#ifndef DELTA_H
#define DELTA_H
#ifdef _WIN32
#pragma once
#endif
#include "maintypes.h"
#define DELTA_MAX_FIELDS 56 // 7*8
#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 +70,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 +80,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 +103,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)
@ -113,10 +136,16 @@ int DELTA_TestDelta(unsigned char *from, unsigned char *to, delta_t *pFields);
int DELTA_CountSendFields(delta_t *pFields);
void DELTA_MarkSendFields(unsigned char *from, unsigned char *to, delta_t *pFields);
void DELTA_SetSendFlagBits(delta_t *pFields, int *bits, int *bytecount);
qboolean DELTA_IsFieldMarked(delta_t* pFields, int fieldNumber);
void DELTA_WriteMarkedFields(unsigned char *from, unsigned char *to, delta_t *pFields);
int DELTA_CheckDelta(unsigned char *from, unsigned char *to, delta_t *pFields);
int DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void));
int _DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void), int sendfields);
qboolean DELTA_CheckDelta(unsigned char *from, unsigned char *to, delta_t *pFields);
#ifdef REHLDS_FIXES //Fix for https://github.com/dreamstalker/rehlds/issues/24
qboolean DELTA_WriteDeltaForceMask(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void), void* pForceMask);
#endif
qboolean DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void));
qboolean _DELTA_WriteDelta(unsigned char *from, unsigned char *to, qboolean force, delta_t *pFields, void(*callback)(void), qboolean sendfields);
int DELTA_ParseDelta(unsigned char *from, unsigned char *to, delta_t *pFields);
void DELTA_AddEncoder(char *name, void(*conditionalencode)(struct delta_s *, const unsigned char *, const unsigned char *));
void DELTA_ClearEncoders(void);
@ -145,5 +174,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

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

@ -0,0 +1,581 @@
#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
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;
}
}
//calculate blocks that we should check
for (unsigned int i = 0; i < jitdesc.numblocks; i++) {
if (jitdesc.blocks[i].numFields > 0) {
jitdesc.itrBlocks[jitdesc.numItrBlocks].memblockId = i;
jitdesc.itrBlocks[jitdesc.numItrBlocks].memblock = &jitdesc.blocks[i];
jitdesc.itrBlocks[jitdesc.numItrBlocks].prefetchBlockId = -1;
jitdesc.numItrBlocks++;
}
}
//decide which blocks we should prefetch
for (unsigned int i = 0; i < jitdesc.numItrBlocks; i++) {
unsigned int prefetchBlkId = (i + 1) * 4;
if (prefetchBlkId >= jitdesc.numblocks)
break;
jitdesc.itrBlocks[i].prefetchBlockId = prefetchBlkId;
}
}
class CDeltaClearMarkFieldsJIT;
class CDeltaJit {
public:
CDeltaClearMarkFieldsJIT* cleanMarkCheckFunc;
delta_t* delta;
int markedFieldsMaskSize;
delta_marked_mask_t marked_fields_mask;
int mfm_sse_highbits[2]; //High 64 bits for manipulating marked_fields_mask via SSE registers
delta_marked_mask_t originalMarkedFieldsMask; //mask based on data, before calling the conditional encoder
int omfm_sse_highbits[2]; //High 64 bits for manipulating marked_fields_mask via SSE registers
CDeltaJit(delta_t* _delta, CDeltaClearMarkFieldsJIT* _cleanMarkCheckFunc);
virtual ~CDeltaJit();
};
class CDeltaClearMarkFieldsJIT : public jitasm::function<int, CDeltaClearMarkFieldsJIT, void*, void*, void*, void*> {
public:
deltajitdata_t *jitdesc;
deltajit_marked_count_type_t countType;
XmmReg marked_fields_mask = xmm7;
CDeltaClearMarkFieldsJIT(deltajitdata_t *_jitdesc, deltajit_marked_count_type_t _countType)
: jitdesc(_jitdesc), countType(_countType) {
}
void checkFieldMask(jitasm::Frontend::Reg32& mask, deltajit_memblock_field* jitField);
Result main(Addr src, Addr dst, Addr deltaJit, Addr pForceMarkMask);
void processStrings(Addr src, Addr dst);
void callConditionalEncoder(Addr src, Addr dst, Addr deltaJit);
void calculateBytecount();
};
void CDeltaClearMarkFieldsJIT::checkFieldMask(jitasm::Frontend::Reg32& mask, deltajit_memblock_field* jitField) {
test(mask, (uint16)jitField->mask);
setnz(al);
movzx(edx, al);
}
void CDeltaClearMarkFieldsJIT::callConditionalEncoder(Addr src, Addr dst, Addr deltaJit) {
//This generator expects that following registers are already initialized:
// esi = src
// edi = dst
int deltaOffset = (offsetof(CDeltaJit, delta));
int condEncoderOffset = (offsetof(delta_t, conditionalencode));
mov(eax, ptr[deltaJit]);
mov(eax, ptr[eax + deltaOffset]);
mov(ecx, dword_ptr[eax + condEncoderOffset]);
If(ecx != 0);
push(edi);
push(esi);
push(eax);
call(ecx);
add(esp, 12);
EndIf();
}
void CDeltaClearMarkFieldsJIT::calculateBytecount() {
//This generator expects that following registers are already initialized:
//ebx = delta
size_t delta_markbits_offset = offsetof(CDeltaJit, marked_fields_mask);
mov(eax, dword_ptr[ebx + delta_markbits_offset]);
xor_(edx, edx);
// 0-7
mov(ecx, 1);
test(eax, 0xFF);
cmovnz(edx, ecx);
// 8-15
if (jitdesc->numFields > 7)
{
mov(esi, 2);
test(eax, 0xFF00);
cmovnz(edx, esi);
}
// 16-23
if (jitdesc->numFields > 15)
{
mov(ecx, 3);
test(eax, 0xFF0000);
cmovnz(edx, ecx);
}
// 24-31
if (jitdesc->numFields > 23)
{
mov(esi, 4);
test(eax, 0xFF000000);
cmovnz(edx, esi);
}
if (jitdesc->numFields > 31)
{
mov(eax, dword_ptr[ebx + delta_markbits_offset + 4]);
// 32-39
mov(ecx, 5);
test(eax, 0xFF);
cmovnz(edx, ecx);
// 40-47
if (jitdesc->numFields > 39)
{
mov(esi, 6);
test(eax, 0xFF00);
cmovnz(edx, esi);
}
// 48-55
if (jitdesc->numFields > 47)
{
mov(ecx, 7);
test(eax, 0xFF0000);
cmovnz(edx, ecx);
}
// maxfields is 56
}
size_t delta_masksize_offset = offsetof(CDeltaJit, markedFieldsMaskSize);
mov(dword_ptr[ebx + delta_masksize_offset], edx);
}
CDeltaClearMarkFieldsJIT::Result CDeltaClearMarkFieldsJIT::main(Addr src, Addr dst, Addr deltaJit, Addr pForceMarkMask)
{
#ifndef REHLDS_FIXES
sub(esp, 12); //some local storage is required for precise DT_TIMEWINDOW marking
#endif
/*
Registers usage:
esi = src
edi = dst
xmm0-xmm2: loaded src
xmm3-xmm5: loaded dst
xmm6: temp
xmm7: marked fields mask
*/
mov(esi, ptr[src]);
mov(edi, ptr[dst]);
int dataXmmCounter = 0; // from 0 to 2 => 3 pairs of registers
jitasm::Frontend::XmmReg src_xmm[3] = { xmm0, xmm1, xmm2 };
jitasm::Frontend::XmmReg dst_xmm[3] = { xmm3, xmm4, xmm5 };
// overall mask is in xmm7 (marked_fields_mask)
auto xmm_tmp = xmm6;
if (jitdesc->numItrBlocks > 0) {
movdqu(src_xmm[0], xmmword_ptr[esi + (jitdesc->itrBlocks[0].memblockId * 16)]);
movdqu(dst_xmm[0], xmmword_ptr[edi + (jitdesc->itrBlocks[0].memblockId * 16)]);
}
if (jitdesc->numItrBlocks > 1) {
movdqu(src_xmm[1], xmmword_ptr[esi + (jitdesc->itrBlocks[1].memblockId * 16)]);
movdqu(dst_xmm[1], xmmword_ptr[edi + (jitdesc->itrBlocks[1].memblockId * 16)]);
}
if (jitdesc->numItrBlocks > 2) {
movdqu(src_xmm[2], xmmword_ptr[esi + (jitdesc->itrBlocks[2].memblockId * 16)]);
movdqu(dst_xmm[2], xmmword_ptr[edi + (jitdesc->itrBlocks[2].memblockId * 16)]);
}
auto blockMask = ecx;
xor_(blockMask, blockMask);
pxor(marked_fields_mask, marked_fields_mask);
for (unsigned int i = 0; i < jitdesc->numItrBlocks; i++) {
auto block = jitdesc->itrBlocks[i].memblock;
auto itrBlock = &jitdesc->itrBlocks[i];
//do far prefetch
if (itrBlock->prefetchBlockId != -1) {
prefetcht0(byte_ptr[esi + (itrBlock->prefetchBlockId * 16)]);
prefetcht0(byte_ptr[edi + (itrBlock->prefetchBlockId * 16)]);
}
pcmpeqb(src_xmm[dataXmmCounter], dst_xmm[dataXmmCounter]);
pmovmskb(blockMask, src_xmm[dataXmmCounter]);
not_(blockMask);
//preload next blocks
if (i + 3 < jitdesc->numItrBlocks) {
movdqu(src_xmm[dataXmmCounter], xmmword_ptr[esi + (jitdesc->itrBlocks[i + 3].memblockId * 16)]);
movdqu(dst_xmm[dataXmmCounter], xmmword_ptr[edi + (jitdesc->itrBlocks[i + 3].memblockId * 16)]);
}
dataXmmCounter++;
if (dataXmmCounter > 2) {
dataXmmCounter -= 3;
}
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(edx, al);
} else {
continue;
}
} else {
checkFieldMask(blockMask, jitField);
}
#else
checkFieldMask(blockMask, jitField);
#endif
// set bit in send mask
movd(xmm_tmp, edx);
psllq(xmm_tmp, jitField->field->id);
por(marked_fields_mask, xmm_tmp);
}
}
//apply 'force mark' mask if it's present
mov(eax, ptr[pForceMarkMask]);
If(eax != 0);
//mask for cleaning garbage in high 64 bits
mov(edx, -1);
movd(xmm0, edx);
movd(xmm1, edx);
psllq(xmm0, 32);
por(xmm0, xmm1);
movdqu(xmm_tmp, xmmword_ptr[eax]);
pand(xmm_tmp, xmm0); //clean high 64 bits
por(marked_fields_mask, xmm_tmp); //apply the 'force' mask
EndIf();
size_t delta_markbits_offset = offsetof(CDeltaJit, marked_fields_mask);
//Save mask from SSE register to CDeltaJit::marked_fields_mask and CDeltaJit::originalMarkedFieldsMask
mov(ebx, ptr[deltaJit]);
movdqu(xmmword_ptr[ebx + delta_markbits_offset], marked_fields_mask);
movdqu(xmmword_ptr[ebx + offsetof(CDeltaJit, originalMarkedFieldsMask)], marked_fields_mask);
processStrings(src, dst);
//emit conditional encoder call
callConditionalEncoder(src, dst, deltaJit);
// check if mask is empty
mov(edi, dword_ptr[ebx + delta_markbits_offset]);
or_(edi, dword_ptr[ebx + delta_markbits_offset + 4]);
If(edi != 0);
calculateBytecount();
Else();
//set maskSize to 0 if there are no marked fields
size_t delta_masksize_offset = offsetof(CDeltaJit, markedFieldsMaskSize);
xor_(edx, edx);
mov(dword_ptr[ebx + delta_masksize_offset], edx);
EndIf();
#ifndef REHLDS_FIXES
add(esp, 12); //some local storage is required for precise DT_TIMEWINDOW marking
#endif // REHLDS_FIXES
return edx;
}
void CDeltaClearMarkFieldsJIT::processStrings(Addr src, Addr dst) {
//This generator expects that following registers are already initialized:
// esi = src
// edi = dst
// ebx = deltaJit
size_t delta_markbits_offset = offsetof(CDeltaJit, marked_fields_mask);
//strings
for (unsigned int i = 0; i < jitdesc->numFields; i++) {
auto jitField = &jitdesc->fields[i];
if (jitField->type != DT_STRING)
continue;
// will be parallel
lea(eax, ptr[esi + jitField->offset]);
lea(edx, ptr[edi + jitField->offset]);
push(eax);
push(edx);
mov(ecx, (size_t)&Q_stricmp);
call(ecx);
add(esp, 8);
xor_(ecx, ecx);
test(eax, eax);
setnz(cl);
shl(ecx, jitField->id & 31);
or_(ptr[ebx + delta_markbits_offset + ((jitField->id > 31) ? 4 : 0)], ecx);
}
}
CDeltaJit::CDeltaJit(delta_t* _delta, CDeltaClearMarkFieldsJIT* _cleanMarkCheckFunc) {
delta = _delta;
cleanMarkCheckFunc = _cleanMarkCheckFunc;
}
CDeltaJit::~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, DJ_M_CHECK);
cleanMarkCheckFunc->Assemble();
cleanMarkCheckFunc->jitdesc = NULL;
CDeltaJit* deltaJit = new CDeltaJit(delta, cleanMarkCheckFunc);
RegisterDeltaJit(delta, deltaJit);
}
CDeltaJit* DELTAJit_LookupDeltaJit(const char* callsite, delta_t *pFields) {
CDeltaJit* deltaJit = g_DeltaJitRegistry.GetJITByDelta(pFields);
if (!deltaJit) {
rehlds_syserror("%s: JITted delta encoder not found for delta %p", callsite, pFields);
return NULL;
}
return deltaJit;
}
NOINLINE int DELTAJit_Fields_Clear_Mark_Check(unsigned char *from, unsigned char *to, delta_t *pFields, void* pForceMarkMask) {
CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields);
CDeltaClearMarkFieldsJIT &func = *deltaJit->cleanMarkCheckFunc;
return func(from, to, deltaJit, pForceMarkMask);
}
void DELTAJit_SetSendFlagBits(delta_t *pFields, int *bits, int *bytecount) {
CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields);
bits[0] = deltaJit->marked_fields_mask.u32[0];
bits[1] = deltaJit->marked_fields_mask.u32[1];
*bytecount = deltaJit->markedFieldsMaskSize;
}
void DELTAJit_SetFieldByIndex(struct delta_s *pFields, int fieldNumber) {
CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields);
if (fieldNumber > 31)
deltaJit->marked_fields_mask.u32[1] |= (1 << (fieldNumber & 0x1F));
else
deltaJit->marked_fields_mask.u32[0] |= (1 << fieldNumber);
}
void DELTAJit_UnsetFieldByIndex(struct delta_s *pFields, int fieldNumber) {
CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields);
if (fieldNumber > 31)
deltaJit->marked_fields_mask.u32[1] &= ~(1 << (fieldNumber & 0x1F));
else
deltaJit->marked_fields_mask.u32[0] &= ~(1 << fieldNumber);
}
qboolean DELTAJit_IsFieldMarked(delta_t* pFields, int fieldNumber) {
CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields);
if (fieldNumber > 31)
return deltaJit->marked_fields_mask.u32[1] & (1 << (fieldNumber & 0x1F));
return deltaJit->marked_fields_mask.u32[0] & (1 << fieldNumber);
}
uint64 DELTAJit_GetOriginalMask(delta_t* pFields) {
CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields);
return deltaJit->originalMarkedFieldsMask.u64;
}
uint64 DELTAJit_GetMaskU64(delta_t* pFields) {
CDeltaJit* deltaJit = DELTAJit_LookupDeltaJit(__FUNCTION__, pFields);
return deltaJit->marked_fields_mask.u64;
}
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
}

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

@ -0,0 +1,85 @@
#pragma once
#include "maintypes.h"
#define DELTAJIT_MAX_BLOCKS 32
#define DELTAJIT_MAX_FIELDS 56
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 deltajit_memblock_itr_t {
int memblockId;
deltajit_memblock* memblock;
int prefetchBlockId;
};
struct deltajitdata_t {
unsigned int numblocks;
deltajit_memblock blocks[DELTAJIT_MAX_BLOCKS];
unsigned int numFields;
deltajit_field fields[DELTAJIT_MAX_FIELDS];
unsigned int numItrBlocks;
deltajit_memblock_itr_t itrBlocks[DELTAJIT_MAX_BLOCKS];
};
enum deltajit_marked_count_type_t {
DJ_M_DONT_COUNT,
DJ_M_CHECK,
//DJ_M_COUNT, //not implemented yet
};
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();
};
union delta_marked_mask_t {
uint8 u8[8];
uint32 u32[2];
uint64 u64;
};
extern CDeltaJitRegistry g_DeltaJitRegistry;
extern int DELTAJit_Fields_Clear_Mark_Check(unsigned char *from, unsigned char *to, delta_t *pFields, void* pForceMarkMask);
extern void DELTAJit_SetSendFlagBits(delta_t *pFields, int *bits, int *bytecount);
extern void DELTAJit_SetFieldByIndex(struct delta_s *pFields, int fieldNumber);
extern void DELTAJit_UnsetFieldByIndex(struct delta_s *pFields, int fieldNumber);
extern qboolean DELTAJit_IsFieldMarked(delta_t* pFields, int fieldNumber);
/* Returns original mask, before it was changed by the conditional encoder */
extern uint64 DELTAJit_GetOriginalMask(delta_t* pFields);
extern uint64 DELTAJit_GetMaskU64(delta_t* pFields);

View File

@ -4,7 +4,7 @@ class CStringPoolMap : public CStaticMap<const char*, char*, 8, 2048> {
protected:
virtual uint32 hash(const char* const &val) {
unsigned int len = strlen(val);
return crc32((const uint8*)val, len);
return crc32c((const uint8*)val, len);
}
virtual bool equals(const char* const &val1, const char* const &val2) {

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];
@ -481,8 +488,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)_DotProduct(mid, tex->vecs[0]);
dt = (int)_DotProduct(mid, tex->vecs[1]);
ds = (int)(_DotProduct(mid, tex->vecs[0]) + tex->vecs[0][3]);
dt = (int)(_DotProduct(mid, tex->vecs[1]) + tex->vecs[1][3]);
if (ds >= surf->texturemins[0])
{
if (dt >= surf->texturemins[1])
@ -1069,7 +1076,12 @@ int PF_precache_sound_I(const char *s)
{
if (!g_psv.sound_precache[i])
{
#ifdef REHLDS_FIXES
// For more information, see EV_Precache
g_psv.sound_precache[i] = ED_NewString(s);
#else
g_psv.sound_precache[i] = s;
#endif // REHLDS_FIXES
return i;
}
@ -1124,8 +1136,15 @@ short unsigned int EV_Precache(int type, const char *psz)
char* evScript = (char*) COM_LoadFile(szpath, 5, &scriptSize);
if (!evScript)
Host_Error("EV_Precache: file %s missing from server\n", psz);
#ifdef REHLDS_FIXES
// Many modders don't know that the resource names passed to precache functions must be a static strings.
// Also some metamod modules can be unloaded during the server running.
// Thereafter the pointers to resource names, precached by this modules becomes invalid and access to them will cause segfault error.
// Reallocating strings in the rehlds temporary hunk memory helps to avoid these problems.
g_psv.event_precache[i].filename = ED_NewString(psz);
#else
g_psv.event_precache[i].filename = psz;
#endif // REHLDS_FIXES
g_psv.event_precache[i].filesize = scriptSize;
g_psv.event_precache[i].pszScript = evScript;
g_psv.event_precache[i].index = i;
@ -1405,15 +1424,31 @@ int PF_precache_model_I(const char *s)
{
if (!g_psv.model_precache[i])
{
#ifdef REHLDS_FIXES
// For more information, see EV_Precache
g_psv.model_precache[i] = ED_NewString(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.",
@ -1424,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);
}
@ -1447,7 +1488,12 @@ int PF_precache_generic_I(char *s)
{
if (!g_psv.generic_precache[i])
{
#ifdef REHLDS_FIXES
// For more information, see EV_Precache
g_psv.generic_precache[i] = ED_NewString(s);
#else
g_psv.generic_precache[i] = s;
#endif // REHLDS_FIXES
return i;
}

View File

@ -1,5 +1,5 @@
#include "precompiled.h"
#include "sys_shared.cpp"
#include "crc32.cpp"
#include "crc32c.cpp"
#include "interface.cpp"

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;
@ -493,13 +485,13 @@ void SV_AllocPacketEntities(client_frame_t *frame, int numents)
{
if (frame)
{
#ifdef REHLDS_FIXES
#ifdef REHLDS_OPT_PEDANTIC
frame->entities.num_entities = numents;
// only alloc for max possible numents
if (!frame->entities.entities)
frame->entities.entities = (entity_state_t *)Mem_ZeroMalloc(sizeof(entity_state_t) * MAX_PACKET_ENTITIES);
#else // REHLDS_FIXES
#else // REHLDS_OPT_PEDANTIC
if (frame->entities.entities)
SV_ClearPacketEntities(frame);
@ -509,7 +501,7 @@ void SV_AllocPacketEntities(client_frame_t *frame, int numents)
frame->entities.num_entities = numents;
frame->entities.entities = (entity_state_t *)Mem_ZeroMalloc(sizeof(entity_state_t) * allocatedslots);
#endif // REHLDS_FIXES
#endif // REHLDS_OPT_PEDANTIC
}
}
@ -660,14 +652,16 @@ void SV_Users_f(void)
/* <a651b> ../engine/sv_main.c:762 */
void SV_CountPlayers(int *clients)
{
*clients = 0;
int count = 0;
client_s *cl = g_psvs.clients;
for (int i = 0; i < g_psvs.maxclients; i++, cl++)
{
if (cl->active || cl->spawned || cl->connected)
(*clients)++;
if (cl->active | cl->spawned | cl->connected)
count++;
}
*clients = count;
}
/* <a68a4> ../engine/sv_main.c:786 */
@ -695,8 +689,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
}
}
@ -1386,11 +1387,17 @@ void SV_WriteClientdataToMessage(client_t *client, sizebuf_t *msg)
else
fdata = &host_client->frames[bits].weapondata[i];
if (DELTA_CheckDelta((byte *)fdata, (byte *)tdata, (delta_t *)g_pweapondelta))
if (DELTA_CheckDelta((byte *)fdata, (byte *)tdata, g_pweapondelta))
{
MSG_WriteBits(1, 1);
MSG_WriteBits(i, 6);
DELTA_WriteDelta((byte *)fdata, (byte *)tdata, TRUE, (delta_t *)g_pweapondelta, NULL);
#if defined (REHLDS_OPT_PEDANTIC) || defined (REHLDS_FIXES)
// all calculations are already done
_DELTA_WriteDelta((byte *)fdata, (byte *)tdata, TRUE, g_pweapondelta, NULL, TRUE);
#else
DELTA_WriteDelta((byte *)fdata, (byte *)tdata, TRUE, g_pweapondelta, NULL);
#endif
}
}
}
@ -3828,6 +3835,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
{
@ -4140,11 +4151,19 @@ int SV_CreatePacketEntities(sv_delta_t type, client_t *client, packet_entities_t
int oldmax;
int numbase;
// fix for https://github.com/dreamstalker/rehlds/issues/24
#ifdef REHLDS_FIXES
int baselineToIdx = -1; //index of the baseline in to->entities[]
uint64 toBaselinesForceMask[MAX_PACKET_ENTITIES];
#endif
numbase = 0;
if (type == sv_packet_delta)
{
client_frame_t *fromframe = &client->frames[SV_UPDATE_MASK & client->delta_sequence];
from = &fromframe->entities;
_mm_prefetch((const char*)&from->entities[0], _MM_HINT_T0);
_mm_prefetch(((const char*)&from->entities[0]) + 64, _MM_HINT_T0);
oldmax = from->num_entities;
MSG_WriteByte(msg, svc_deltapacketentities);
MSG_WriteShort(msg, to->num_entities);
@ -4158,8 +4177,8 @@ int SV_CreatePacketEntities(sv_delta_t type, client_t *client, packet_entities_t
MSG_WriteShort(msg, to->num_entities);
}
newnum = 0;
oldnum = 0;
newnum = 0; //index in to->entities
oldnum = 0; //index in from->entities
MSG_StartBitWriting(msg);
while (1)
{
@ -4190,6 +4209,8 @@ int SV_CreatePacketEntities(sv_delta_t type, client_t *client, packet_entities_t
SV_SetCallback(newindex, FALSE, custom, &numbase, FALSE, 0);
DELTA_WriteDelta((uint8 *)&from->entities[oldnum], (uint8 *)baseline_, FALSE, custom ? g_pcustomentitydelta : (SV_IsPlayerIndex(newindex) ? g_pplayerdelta : g_pentitydelta), &SV_InvokeCallback);
++oldnum;
_mm_prefetch((const char*)&from->entities[oldnum], _MM_HINT_T0);
_mm_prefetch(((const char*)&from->entities[oldnum]) + 64, _MM_HINT_T0);
++newnum;
continue;
}
@ -4200,6 +4221,8 @@ int SV_CreatePacketEntities(sv_delta_t type, client_t *client, packet_entities_t
{
SV_WriteDeltaHeader(oldindex, TRUE, FALSE, &numbase, FALSE, 0, FALSE, 0);
++oldnum;
_mm_prefetch((const char*)&from->entities[oldnum], _MM_HINT_T0);
_mm_prefetch(((const char*)&from->entities[oldnum]) + 64, _MM_HINT_T0);
}
continue;
}
@ -4232,19 +4255,54 @@ int SV_CreatePacketEntities(sv_delta_t type, client_t *client, packet_entities_t
if (!from)
{
int offset = SV_FindBestBaseline(newnum, &baseline_, to->entities, newindex, custom);
_mm_prefetch((const char*)baseline_, _MM_HINT_T0);
_mm_prefetch(((const char*)baseline_) + 64, _MM_HINT_T0);
if (offset)
SV_SetCallback(newindex, 0, custom, &numbase, 1, offset);
// fix for https://github.com/dreamstalker/rehlds/issues/24
#ifdef REHLDS_FIXES
if (offset)
baselineToIdx = newnum - offset;
#endif
}
}
delta_t* delta = custom ? g_pcustomentitydelta : (SV_IsPlayerIndex(newindex) ? g_pplayerdelta : g_pentitydelta);
// fix for https://github.com/dreamstalker/rehlds/issues/24
#ifdef REHLDS_FIXES
DELTA_WriteDeltaForceMask(
(uint8 *)baseline_,
(uint8 *)&to->entities[newnum],
TRUE,
delta,
&SV_InvokeCallback,
baselineToIdx != -1 ? &toBaselinesForceMask[baselineToIdx] : NULL
);
baselineToIdx = -1;
uint64 origMask = DELTAJit_GetOriginalMask(delta);
uint64 usedMask = DELTAJit_GetMaskU64(delta);
uint64 diffMask = origMask ^ usedMask;
//Remember changed fields that was marked in original mask, but unmarked by the conditional encoder
toBaselinesForceMask[newnum] = diffMask & origMask;
#else //REHLDS_FIXES
DELTA_WriteDelta(
(uint8 *)baseline_,
(uint8 *)&to->entities[newnum],
TRUE,
custom ? g_pcustomentitydelta : (SV_IsPlayerIndex(newindex) ? g_pplayerdelta : g_pentitydelta),
delta,
&SV_InvokeCallback
);
#endif //REHLDS_FIXES
++newnum;
}
MSG_WriteBits(0, 16);
@ -4380,7 +4438,7 @@ void SV_EmitPings(client_t *client, sizebuf_t *msg)
/* <a947b> ../engine/sv_main.c:5878 */
void SV_WriteEntitiesToClient(client_t *client, sizebuf_t *msg)
{
full_packet_entities_t fullpack;
client_frame_t *frame = &client->frames[SV_UPDATE_MASK & client->netchan.outgoing_sequence];
unsigned char *pvs = NULL;
@ -4388,72 +4446,68 @@ void SV_WriteEntitiesToClient(client_t *client, sizebuf_t *msg)
gEntityInterface.pfnSetupVisibility((edict_t*)client->pViewEntity, client->edict, &pvs, &pas);
unsigned char *pSet = pvs;
#ifndef REHLDS_FIXES
// don't reallocate entity states
SV_ClearPacketEntities(frame);
#endif // REHLDS_FIXES
packet_entities_t *pack = &frame->entities;
fullpack.num_entities = 0;
qboolean sendping = SV_ShouldUpdatePing(client);
// for REHLDS_OPT_PEDANTIC: Allocate the MAX_PACKET_ENTITIES ents in the frame's storage
// This allows us to avoid intermediate 'fullpack' storage
#ifdef REHLDS_OPT_PEDANTIC
SV_AllocPacketEntities(frame, MAX_PACKET_ENTITIES);
packet_entities_t *curPack = &frame->entities;
curPack->num_entities = 0;
#else
SV_ClearPacketEntities(frame);
full_packet_entities_t fullpack;
fullpack.num_entities = 0;
full_packet_entities_t* curPack = &fullpack;
#endif // REHLDS_OPT_PEDANTIC
qboolean sendping = SV_ShouldUpdatePing(client);
int flags = client->lw != 0;
#ifdef REHLDS_FIXES
int e;
for (e = 1; e <= g_psvs.maxclients; e++)
{
client_t *cl = &g_psvs.clients[e - 1];
if( ( !cl->active && !cl->spawned ) || cl->proxy )
continue;
qboolean add = gEntityInterface.pfnAddToFullPack(&fullpack.entities[fullpack.num_entities], e, &g_psv.edicts[e], host_client->edict, flags, TRUE, pSet);
qboolean add = gEntityInterface.pfnAddToFullPack(&curPack->entities[curPack->num_entities], e, &g_psv.edicts[e], host_client->edict, flags, TRUE, pSet);
if (add)
++fullpack.num_entities;
++curPack->num_entities;
}
for (; e < g_psv.num_edicts; e++)
{
if (fullpack.num_entities >= MAX_PACKET_ENTITIES)
if (curPack->num_entities >= MAX_PACKET_ENTITIES)
{
Con_DPrintf("Too many entities in visible packet list.\n");
break;
}
qboolean add = gEntityInterface.pfnAddToFullPack(&fullpack.entities[fullpack.num_entities], e, &g_psv.edicts[e], host_client->edict, flags, FALSE, pSet);
if (add)
++fullpack.num_entities;
}
#else // REHLDS_FIXES
for (int e = 1; e < g_psv.num_edicts; e++)
{
edict_t *ent = &g_psv.edicts[e];
int player = 0;
if (e >= 1 && e <= g_psvs.maxclients)
{
client_t *cl = &g_psvs.clients[e - 1];
if ((!cl->active && !cl->spawned) || cl->proxy)
continue;
edict_t* ent = &g_psv.edicts[e];
player = 1;
#ifdef REHLDS_OPT_PEDANTIC
//Part of gamedll's code is moved here to decrease amount of calls to AddToFullPack()
//We don't even try to transmit entities without model as well as invisible entities
if (ent->v.modelindex && !(ent->v.effects & EF_NODRAW)) {
qboolean add = gEntityInterface.pfnAddToFullPack(&curPack->entities[curPack->num_entities], e, &g_psv.edicts[e], host_client->edict, flags, FALSE, pSet);
if (add)
++curPack->num_entities;
}
if (fullpack.num_entities >= MAX_PACKET_ENTITIES)
{
Con_DPrintf("Too many entities in visible packet list.\n");
break;
}
qboolean add = gEntityInterface.pfnAddToFullPack(&fullpack.entities[fullpack.num_entities], e, ent, host_client->edict, flags, player, pSet);
#else
qboolean add = gEntityInterface.pfnAddToFullPack(&curPack->entities[curPack->num_entities], e, &g_psv.edicts[e], host_client->edict, flags, FALSE, pSet);
if (add)
++fullpack.num_entities;
}
#endif // REHLDS_FIXES
++curPack->num_entities;
#endif //REHLDS_OPT_PEDANTIC
}
//for REHLDS_FIXES: Entities are already in the frame's storage, no need to copy them
#ifndef REHLDS_OPT_PEDANTIC
SV_AllocPacketEntities(frame, fullpack.num_entities);
if (pack->num_entities)
Q_memcpy(pack->entities, fullpack.entities, sizeof(entity_state_t) * pack->num_entities);
#endif
SV_EmitPacketEntities(client, pack, msg);
SV_EmitEvents(client, pack, msg);
@ -4849,6 +4903,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])
@ -4857,6 +4917,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);
}
@ -5461,6 +5522,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);
@ -5573,6 +5639,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;
@ -5582,6 +5655,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));
@ -6785,6 +6865,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 */
@ -6822,6 +6906,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 */
@ -7008,6 +7096,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

@ -1097,8 +1097,11 @@ void SV_Physics_Toss(edict_t *ent)
}
ClipVelocity(ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);
if (trace.plane.normal[2] <= 0.7f)
if (trace.plane.normal[2] <= 0.7)
{
SV_CheckWaterTransition(ent);
return;
}
move[0] = ent->v.basevelocity[0] + ent->v.velocity[0];
move[1] = ent->v.basevelocity[1] + ent->v.velocity[1];
@ -1131,6 +1134,7 @@ void SV_Physics_Toss(edict_t *ent)
ent->v.avelocity[0] = vec3_origin[0];
ent->v.avelocity[1] = vec3_origin[1];
ent->v.avelocity[2] = vec3_origin[2];
SV_CheckWaterTransition(ent);
} /* size: 3408000 */
/* <b655d> ../engine/sv_phys.c:1668 */

View File

@ -1226,8 +1226,17 @@ void SV_SetupMove(client_t *_host_client)
for (int j = 0; j < nextFrame->entities.num_entities; j++)
{
state = &nextFrame->entities.entities[j];
#ifdef REHLDS_OPT_PEDANTIC
if (state->number <= 0)
continue;
if (state->number > g_psvs.maxclients)
break; // players are always in the beginning of the list, no need to look more
#else
if (state->number <= 0 || state->number > g_psvs.maxclients)
continue;
#endif
pos = &truepositions[state->number - 1];
if (pos->deadflag)

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;

File diff suppressed because it is too large Load Diff

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,27 @@ 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_LogSzAlloc(int counter, int cursize, int maxsize, int flags) {
g_RehldsDebugLog << "SZAlloc(c=" << counter << " sz=" << cursize << " maxsz= " << maxsize << " f=" << flags << ")\n";
g_RehldsDebugLog.flush();
}
void Rehlds_Debug_Init(Module* engine)
{

View File

@ -41,6 +41,9 @@ 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_LogSzAlloc(int counter, int cursize, int maxsize, int flags);
extern void Rehlds_Debug_Init(Module* engine);
#endif

View File

@ -25,6 +25,10 @@
<Configuration>Release Play</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release Swds Play|Win32">
<Configuration>Release Swds Play</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
@ -49,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" />
@ -98,21 +103,25 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Test Fixes|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\hookers\hooker.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Tests|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Test Fixes|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\hookers\main.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\hookers\main_swds.cpp">
<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'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Tests|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Test Fixes|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
@ -131,19 +140,19 @@
<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>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Tests|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Test Fixes|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\public\registry.cpp" />
<ClCompile Include="..\public\rehlds\crc32.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ClCompile Include="..\public\rehlds\crc32c.cpp">
<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)'=='Tests|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Swds Play|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Test Fixes|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\public\rehlds\sys_shared.cpp">
@ -154,6 +163,7 @@
<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>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Tests|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Test Fixes|Win32'">true</ExcludedFromBuild>
</ClCompile>
@ -167,6 +177,7 @@
<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>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Tests|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Test Fixes|Win32'">true</ExcludedFromBuild>
</ClCompile>
@ -191,8 +202,10 @@
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug Record|Win32'">precompiled.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release Play|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">Create</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">precompiled.h</PrecompiledHeaderFile>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release Play|Win32'">precompiled.h</PrecompiledHeaderFile>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">precompiled.h</PrecompiledHeaderFile>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Tests|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Test Fixes|Win32'">Create</PrecompiledHeader>
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Tests|Win32'">precompiled.h</PrecompiledHeaderFile>
@ -213,36 +226,58 @@
<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\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)'=='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)'=='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>
<ClCompile Include="..\unittests\crc32c_tests.cpp" />
<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>
<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">
<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>
</ItemGroup>
<ItemGroup>
@ -339,6 +374,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" />
@ -411,7 +447,7 @@
<ClInclude Include="..\public\rehlds\bspfile.h" />
<ClInclude Include="..\public\rehlds\cmd_rehlds.h" />
<ClInclude Include="..\public\rehlds\common_rehlds.h" />
<ClInclude Include="..\public\rehlds\crc32.h" />
<ClInclude Include="..\public\rehlds\crc32c.h" />
<ClInclude Include="..\public\rehlds\custom.h" />
<ClInclude Include="..\public\rehlds\customentity.h" />
<ClInclude Include="..\public\rehlds\d_local.h" />
@ -571,6 +607,13 @@
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_xp</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
@ -601,6 +644,9 @@
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Play|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetName>filesystem_stdio</TargetName>
@ -629,6 +675,9 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Play|Win32'">
<TargetName>filesystem_stdio</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">
<TargetName>swds</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<PreBuildEvent>
<Command>IF EXIST "$(ProjectDir)PreBuild.bat" (CALL "$(ProjectDir)PreBuild.bat" "$(ProjectDir)..\version\" "$(ProjectDir)..\")</Command>
@ -677,7 +726,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_SELF;REHLDS_FIXES;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>REHLDS_FLIGHT_REC;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>
@ -829,6 +878,7 @@
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -936,7 +986,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>REHLDS_FLIGHT_REC;REHLDS_SELF;HOOK_ENGINE;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalOptions>/arch:IA32 %(AdditionalOptions)</AdditionalOptions>
<PrecompiledHeader>Use</PrecompiledHeader>
@ -964,6 +1014,50 @@
<Inputs>subversion.always.run</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Swds Play|Win32'">
<PreBuildEvent>
<Command>IF EXIST "$(ProjectDir)PreBuild.bat" (CALL "$(ProjectDir)PreBuild.bat" "$(ProjectDir)..\version\" "$(ProjectDir)..\")</Command>
<Message>Setup version from SVN revision</Message>
</PreBuildEvent>
<ClCompile>
<AdditionalIncludeDirectories>$(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)</AdditionalIncludeDirectories>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>REHLDS_FLIGHT_REC;REHLDS_OPT_PEDANTIC;REHLDS_SELF;REHLDS_CHECKS;USE_BREAKPAD_HANDLER;DEDICATED;SWDS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalOptions>/arch:IA32 %(AdditionalOptions)</AdditionalOptions>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>psapi.lib;ws2_32.lib;$(ProjectDir)../lib/steam_api.lib;%(AdditionalDependencies)</AdditionalDependencies>
<MinimumRequiredVersion>
</MinimumRequiredVersion>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<FixedBaseAddress>
</FixedBaseAddress>
<BaseAddress>0x4970000</BaseAddress>
</Link>
<PostBuildEvent>
<Command>IF EXIST "$(ProjectDir)PostBuild_swds.bat" (CALL "$(ProjectDir)PostBuild_swds.bat" "$(TargetDir)" "$(TargetName)" "$(TargetExt)" "$(ProjectDir)")</Command>
<Message>Automatic deployment script</Message>
</PostBuildEvent>
<CustomBuildStep>
<Command>echo Empty Action</Command>
<Message>Force build to run Pre-Build event</Message>
<Outputs>subversion.always.run</Outputs>
<Inputs>subversion.always.run</Inputs>
</CustomBuildStep>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -307,9 +307,6 @@
<ClCompile Include="..\public\rehlds\sys_shared.cpp">
<Filter>public\rehlds</Filter>
</ClCompile>
<ClCompile Include="..\public\rehlds\crc32.cpp">
<Filter>public\rehlds</Filter>
</ClCompile>
<ClCompile Include="..\engine\ed_strpool.cpp">
<Filter>engine\common</Filter>
</ClCompile>
@ -325,6 +322,18 @@
<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>
<ClCompile Include="..\public\rehlds\crc32c.cpp">
<Filter>public\rehlds</Filter>
</ClCompile>
<ClCompile Include="..\unittests\crc32c_tests.cpp">
<Filter>unittests</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\hookers\memory.h">
@ -984,9 +993,6 @@
<ClInclude Include="..\public\rehlds\sys_shared.h">
<Filter>public\rehlds</Filter>
</ClInclude>
<ClInclude Include="..\public\rehlds\crc32.h">
<Filter>public\rehlds</Filter>
</ClInclude>
<ClInclude Include="..\public\rehlds\static_map.h">
<Filter>public\rehlds</Filter>
</ClInclude>
@ -1032,6 +1038,12 @@
<ClInclude Include="..\public\rehlds\bspfile.h">
<Filter>public\rehlds</Filter>
</ClInclude>
<ClInclude Include="..\engine\delta_jit.h">
<Filter>engine</Filter>
</ClInclude>
<ClInclude Include="..\public\rehlds\crc32c.h">
<Filter>public\rehlds</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\linux\appversion.sh">

View File

@ -1,133 +0,0 @@
/* The implementation here was originally done by Gary S. Brown. I have
borrowed the tables directly, and made some minor changes to the
crc32-function (including changing the interface). //ylo */
/* ============================================================= */
/* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */
/* code or tables extracted from it, as desired without restriction. */
/* */
/* First, the polynomial itself and its table of feedback terms. The */
/* polynomial is */
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
/* */
/* Note that we take it "backwards" and put the highest-order term in */
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
/* the MSB being 1. */
/* */
/* Note that the usual hardware shift register implementation, which */
/* is what we're using (we're merely optimizing it by doing eight-bit */
/* chunks at a time) shifts bits into the lowest-order term. In our */
/* implementation, that means shifting towards the right. Why do we */
/* do it this way? Because the calculated CRC must be transmitted in */
/* order from highest-order term to lowest-order term. UARTs transmit */
/* characters in order from LSB to MSB. By storing the CRC this way, */
/* we hand it to the UART in the order low-byte to high-byte; the UART */
/* sends each low-bit to hight-bit; and the result is transmission bit */
/* by bit from highest- to lowest-order term without requiring any bit */
/* shuffling on our part. Reception works similarly. */
/* */
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
/* */
/* The table can be generated at runtime if desired; code to do so */
/* is shown later. It might not be obvious, but the feedback */
/* terms simply represent the results of eight shift/xor opera- */
/* tions for all combinations of data and CRC register values. */
/* */
/* The values must be right-shifted by eight bits by the "updcrc" */
/* logic; the shift must be unsigned (bring in zeroes). On some */
/* hardware you could probably optimize the shift in assembler by */
/* using byte-swap instructions. */
/* polynomial $edb88320 */
/* */
/* -------------------------------------------------------------------- */
#include "crc32.h"
#include "sys_shared.h"
static uint32 crc32_tab[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
uint32 crc32_t_nosse(uint32 iCRC, const uint8 *s, unsigned int len) {
uint32 crc32val = iCRC;
for (unsigned int i = 0; i < len; i++) {
crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
}
return crc32val;
}
uint32 crc32_t(uint32 iCRC, const uint8 *s, unsigned int len) {
if (!cpuinfo.sse4_2) {
return crc32_t_nosse(iCRC, s, len);
}
uint32 crc32val = iCRC;
unsigned int i = 0;
for (; i < (len >> 2); i += 4) {
crc32val = _mm_crc32_u32(crc32val, *(uint32*)&s[i]);
}
for (; i < len; i++) {
crc32val = _mm_crc32_u8(crc32val, s[i]);
}
return crc32val;
}
uint32 crc32(const uint8 *buf, unsigned int len) {
return crc32_t(0, buf, len);
}

View File

@ -1,21 +0,0 @@
/*
* $Id: crc32.h,v 1.1.1.1 1996/02/18 21:38:11 ylo Exp $
* $Log: crc32.h,v $
* Revision 1.1.1.1 1996/02/18 21:38:11 ylo
* Imported ssh-1.2.13.
*
* Revision 1.2 1995/07/13 01:21:45 ylo
* Removed "Last modified" header.
* Added cvs log.
*
* $Endlog$
*/
#pragma once
#include "archtypes.h"
/* This computes a 32 bit CRC of the data in the buffer, and returns the
CRC. The polynomial used is 0xedb88320. */
uint32 crc32(const uint8 *buf, unsigned int len);
uint32 crc32_t(uint32 iCRC, const uint8 *s, unsigned int len);

View File

@ -43,6 +43,10 @@
#include <setjmp.h>
#include <assert.h>
#include <algorithm>
#include <deque>
#include <functional>
#ifdef _WIN32 // WINDOWS
#include <windows.h>
#include <winsock.h>
@ -85,6 +89,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

@ -1,13 +1,13 @@
#pragma once
#include "archtypes.h"
#include "crc32.h"
#include "crc32c.h"
template<typename T_KEY, typename T_VAL, unsigned int ASSOC_2N, unsigned int MAX_VALS>
class CStaticMap {
protected:
virtual uint32 hash(const T_KEY& val) {
return crc32((const unsigned char*)&val, sizeof(T_KEY));
return crc32c((const unsigned char*)&val, sizeof(T_KEY));
}
virtual bool equals(const T_KEY& val1, const T_KEY& val2) {
@ -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 crc32c((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 = crc32c_t8_sse(cksum, cc);
}
} else {
while (*pcc) {
char cc = *(pcc++);
if (cc >= 'A' || cc <= 'Z') {
cc |= 0x20;
}
cksum = crc32c_t8_nosse(cksum, cc);
}
}
return cksum;
}
virtual bool equals(const char* const &val1, const char* const &val2) {
return !_stricmp(val1, val2);
}
public:
CICaseStringKeyStaticMap() {
}
};

View File

@ -31,6 +31,12 @@ uint16 g_FRMsg_AllocEntPrivateData;
cvar_t rehlds_flrec_frame = { "rehlds_flrec_frame", "1", 0, 1.0f, NULL };
cvar_t rehlds_flrec_pvdata = { "rehlds_flrec_privdata", "1", 0, 1.0f, NULL };
void FR_CheckInit() {
#ifdef HOOK_ENGINE
if (!g_FlightRecorder)
FR_Init();
#endif
}
void FR_Dump_f() {
const char* fname = "rehlds_flightrec.bin";
@ -54,23 +60,27 @@ void FR_Rehlds_Init() {
}
void FR_StartFrame() {
FR_CheckInit();
g_FlightRecorder->StartMessage(g_FRMsg_Frame, true);
g_FlightRecorder->WriteDouble(realtime);
g_FlightRecorder->EndMessage(g_FRMsg_Frame, true);
}
void FR_EndFrame() {
FR_CheckInit();
g_FlightRecorder->StartMessage(g_FRMsg_Frame, false);
g_FlightRecorder->EndMessage(g_FRMsg_Frame, false);
}
void FR_AllocEntPrivateData(void* res) {
FR_CheckInit();
g_FlightRecorder->StartMessage(g_FRMsg_AllocEntPrivateData, true);
g_FlightRecorder->WriteUInt32((size_t)res);
g_FlightRecorder->EndMessage(g_FRMsg_AllocEntPrivateData, true);
}
void FR_FreeEntPrivateData(void* data) {
FR_CheckInit();
g_FlightRecorder->StartMessage(g_FRMsg_FreeEntPrivateData, true);
g_FlightRecorder->WriteUInt32((size_t)data);
g_FlightRecorder->EndMessage(g_FRMsg_FreeEntPrivateData, true);

8967
rehlds/rehlds/jitasm.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
#include "mathlib.h"
#include "sys_shared.h"
#include "crc32.h"
#include "crc32c.h"
#include "static_map.h"
#include "ed_strpool.h"

View File

@ -24,6 +24,9 @@ CPlayingEngExtInterceptor::CPlayingEngExtInterceptor(const char* fname, bool str
m_GameServerWrapper = NULL;
m_SteamBreakpadContext = NULL;
m_HeartBeatInterval = 10000000;
m_PrevHeartBeat = 0;
uint32 cmdlineLen = 0;
char cmdLine[2048];
@ -47,6 +50,8 @@ CPlayingEngExtInterceptor::CPlayingEngExtInterceptor(const char* fname, bool str
m_InStream.read(cmdLine, cmdlineLen);
printf("Playing testsuite\nrecorders's cmdline: %s\n", cmdLine);
m_StartTick = ::GetTickCount();
}
void* CPlayingEngExtInterceptor::allocFuncCall()
@ -134,12 +139,20 @@ IEngExtCall* CPlayingEngExtInterceptor::getNextCallInternal(bool peek) {
IEngExtCall* CPlayingEngExtInterceptor::getNextCall(bool peek, bool processCallbacks, ExtCallFuncs expectedOpcode, bool needStart, const char* callSource) {
int size = (int)m_InStream.tellg();
int sizeLeft = m_inStreamSize - size;
maybeHeartBeat(size);
IEngExtCall* cmd = getNextCallInternal(peek);
if (peek) {
return cmd;
}
if (cmd->getOpcode() == ECF_NONE) {
DWORD endTick = ::GetTickCount();
FILE* fl = fopen("rehlds_demo_stats.log", "w");
if (fl) {
fprintf(fl, "Finished playing demo; duration=%umsec", (endTick - m_StartTick));
fclose(fl);
}
TerminateProcess(GetCurrentProcess(), 777);
}
@ -158,7 +171,7 @@ IEngExtCall* CPlayingEngExtInterceptor::getNextCall(bool peek, bool processCallb
}
if (cmd->getOpcode() != expectedOpcode) {
rehlds_syserror("%s: bad opcode; expected %d got %d; size left: %d", __FUNCTION__, expectedOpcode, cmd->getOpcode(), m_inStreamSize - size);
rehlds_syserror("%s: bad opcode; expected %d got %d; size left: %d", __FUNCTION__, expectedOpcode, cmd->getOpcode(), sizeLeft);
}
if (needStart) {
if (!cmd->m_Start) rehlds_syserror("%s: bad fcall %d; expected start flag", __FUNCTION__, cmd->getOpcode());
@ -235,6 +248,13 @@ int CPlayingEngExtInterceptor::getOrRegisterSteamCallback(CCallbackBase* cb) {
return id;
}
void CPlayingEngExtInterceptor::maybeHeartBeat(int readPos) {
if (m_PrevHeartBeat + m_HeartBeatInterval <= readPos) {
m_PrevHeartBeat = readPos;
Con_Printf("%s: readPos=%u\n", __FUNCTION__, readPos);
}
}
uint32 CPlayingEngExtInterceptor::time(uint32* pTime)
{
CStdTimeCall* playCall = dynamic_cast<CStdTimeCall*>(getNextCall(false, false, ECF_CSTD_TIME, true, __FUNCTION__));

View File

@ -132,6 +132,10 @@ private:
CSteamGameServerPlayingWrapper* m_GameServerWrapper;
void* m_SteamBreakpadContext;
int m_HeartBeatInterval;
int m_PrevHeartBeat;
DWORD m_StartTick;
hostent_data_t m_CurrentHostentData;
struct hostent m_CurrentHostent;
@ -150,6 +154,8 @@ private:
int getOrRegisterSteamCallback(CCallbackBase* cb);
void maybeHeartBeat(int readPos);
public:
void* allocFuncCall();
void freeFuncCall(void* fcall);

View File

@ -1,17 +1,22 @@
#include "precompiled.h"
#include "cppunitlite/TestHarness.h"
TEST(BitsWritingReading, MSG, 5000)
TEST(BitsWritingReading, MSG, 1000)
{
// TODO: Move to apropriate Init function
int size = 4 * 1024 * 1024;
Memory_Init(new char[size], size);
SZ_Alloc("net_message", &net_message, 1024);
byte localBuf[1024];
sizebuf_t *buf = &net_message;
buf->buffername = "net_message";
buf->data = localBuf;
buf->maxsize = sizeof(localBuf);
buf->cursize = 0;
buf->flags = SIZEBUF_CHECK_OVERFLOW;
uint32 ff1 = ((uint32)1 << 31) - 1;
uint32 ff2 = ((uint32)1 << 9) - 1;
uint32 ff3 = 0xFFFFFFFF;
uint32 t1, t2, t3;
SZ_Clear(buf);
@ -23,8 +28,8 @@ TEST(BitsWritingReading, MSG, 5000)
MSG_BeginReading();
MSG_StartBitReading(buf);
uint32 t1 = MSG_ReadBits(31);
uint32 t2 = MSG_ReadBits(9);
t1 = MSG_ReadBits(31);
t2 = MSG_ReadBits(9);
MSG_EndBitReading(buf);
UINT32_EQUALS("31/9 Read failed (31)", ff1, t1);
@ -49,6 +54,28 @@ TEST(BitsWritingReading, MSG, 5000)
UINT32_EQUALS("9/31 Read failed (31)", ff2, t2);
SZ_Clear(buf);
MSG_StartBitWriting(buf);
MSG_WriteBits(ff2, 9);
MSG_WriteBits(ff3, 32);
MSG_WriteBits(ff1, 31);
MSG_EndBitWriting(buf);
MSG_BeginReading();
MSG_StartBitReading(buf);
t2 = MSG_ReadBits(9);
t3 = MSG_ReadBits(32);
t1 = MSG_ReadBits(31);
MSG_EndBitReading(buf);
UINT32_EQUALS("9/32/31 Read failed (9)", ff1, t1);
UINT32_EQUALS("9/32/31 Read failed (32)", ff3, t3);
UINT32_EQUALS("9/32/31 Read failed (31)", ff2, t2);
uint32 a2, a1 = 5;
uint32 b2, b1 = 0xEFEF;
uint32 c2, c1 = 0x7AAEAEAE;
@ -86,4 +113,37 @@ TEST(BitsWritingReading, MSG, 5000)
UINT32_EQUALS("7/16/31 Read failed", a1, a2);
UINT32_EQUALS("7/16/31 Read failed", b1, b2);
UINT32_EQUALS("7/16/31 Read failed", c1, c2);
SZ_Clear(buf);
MSG_StartBitWriting(buf);
MSG_WriteBits(a1, 7);
MSG_WriteBits(b1, 16);
MSG_WriteBits(c1, 31);
MSG_WriteBits(a1, 7);
MSG_WriteBits(b1, 16);
MSG_WriteBits(c1, 31);
MSG_EndBitWriting(buf);
MSG_BeginReading();
MSG_StartBitReading(buf);
a2 = MSG_ReadBits(7);
b2 = MSG_ReadBits(16);
c2 = MSG_ReadBits(31);
UINT32_EQUALS("7/16/31 Read failed", a1, a2);
UINT32_EQUALS("7/16/31 Read failed", b1, b2);
UINT32_EQUALS("7/16/31 Read failed", c1, c2);
a2 = MSG_ReadBits(7);
b2 = MSG_ReadBits(16);
c2 = MSG_ReadBits(31);
UINT32_EQUALS("7/16/31 Read failed", a1, a2);
UINT32_EQUALS("7/16/31 Read failed", b1, b2);
UINT32_EQUALS("7/16/31 Read failed", c1, c2);
MSG_EndBitReading(buf);
}

View File

@ -0,0 +1,333 @@
#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)
typedef delta_test_struct_t dts_t;
struct delta_res_t
{
qboolean sendfields;
int bits[2];
int bytecount;
};
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 qboolean _DoMarkFields(void* src, void* dst, delta_t* delta, bool useJit) {
qboolean sendfields;
if (useJit) {
DELTA_ClearFlags(delta);
return DELTAJit_Fields_Clear_Mark_Check((unsigned char*)src, (unsigned char*)dst, delta, NULL);
} else {
DELTA_ClearFlags(delta);
DELTA_MarkSendFields((unsigned char*)src, (unsigned char*)dst, delta);
sendfields = DELTA_CountSendFields(delta);
}
return sendfields;
}
NOINLINE void _MarkAndEnsureCorrectResults(const char* action, delta_t* delta, void* src, void* dst, int useJit, bool changed, const char* szFields) {
delta_description_t* fields[DELTA_MAX_FIELDS];
int numFields = 0;
char localFieldsStr[512];
strcpy(localFieldsStr, szFields);
//parse fields
int prevEnd = -1;
for (char* pcc = localFieldsStr; *pcc; pcc++) {
if (*pcc == ' ') {
*pcc = 0;
int fIdx = DELTA_FindFieldIndex(delta, &localFieldsStr[prevEnd + 1]);
if (fIdx == -1) {
rehlds_syserror("%s: Coult not find field '%s'", &localFieldsStr[prevEnd + 1]);
}
fields[numFields++] = &delta->pdd[fIdx];
prevEnd = pcc - localFieldsStr;
}
}
if (localFieldsStr[0] != 0) {
int fIdx = DELTA_FindFieldIndex(delta, &localFieldsStr[prevEnd + 1]);
if (fIdx == -1) {
rehlds_syserror("%s: Coult not find field '%s'", &localFieldsStr[prevEnd + 1]);
}
fields[numFields++] = &delta->pdd[fIdx];
}
//build expected mask
delta_marked_mask_t expectedMask; expectedMask.u64 = 0;
for (int i = 0; i < numFields; i++) {
delta_description_t* f = fields[i];
int fieldId = f - delta->pdd;
expectedMask.u8[fieldId >> 3] |= (1 << (fieldId & 0x7));
}
if (!changed) {
//invert mask
uint64 existingFieldsMask = 0xFFFFFFFFFFFFFFFF;
existingFieldsMask = existingFieldsMask >> (64 - delta->fieldCount);
expectedMask.u64 = ~expectedMask.u64;
expectedMask.u64 &= existingFieldsMask;
}
//calculate expected bytecount
int expectedBytecount = 0;
for (int i = 0; i < ARRAYSIZE(expectedMask.u8); i++) {
if (expectedMask.u8[i]) {
expectedBytecount = i + 1;
}
}
//do marking
qboolean markResult = _DoMarkFields(src, dst, delta, useJit != 0);
//check marking result
if ((markResult != 0) != (expectedMask.u64 != 0)) {
rehlds_syserror("%s: DoMarkFields returned invalid value %d, expected %s", action, markResult, (expectedMask.u64 == 0) ? "0" : "!0");
}
delta_marked_mask_t returnedMask;
int returnedBytecount;
if (useJit) {
DELTAJit_SetSendFlagBits(delta, (int*)returnedMask.u32, &returnedBytecount);
} else {
DELTA_SetSendFlagBits(delta, (int*)returnedMask.u32, &returnedBytecount);
}
//check per-field marks
if (returnedMask.u64 != expectedMask.u64) {
rehlds_syserror("%s: DoMarkFields returned invalid mask %llX, expected %llX", action, returnedMask.u64, expectedMask.u64);
}
//check bytecount
if (returnedBytecount != expectedBytecount) {
rehlds_syserror("%s: DoMarkFields returned invalid bytecount %d, expected %d", action, returnedBytecount, expectedBytecount);
}
}
NOINLINE void _GetBitmaskAndBytecount(delta_t* delta, int* bits, int* bytecount, int usejit) {
if (usejit) {
DELTAJit_SetSendFlagBits(delta, bits, bytecount);
}
else {
DELTA_SetSendFlagBits(delta, bits, bytecount);
}
}
NOINLINE void _CompareDeltaResults(const char* callsite, delta_res_t* def, delta_res_t* jit, int testscount)
{
for (int i = 0; i < testscount; i++)
{
if (!!def[i].sendfields != !!jit[i].sendfields)
rehlds_syserror("%s: Test %i: !!sendfields not equals %i|%i", callsite, i, !!def[i].sendfields, !!jit[i].sendfields);
if (memcmp(def[i].bits, jit[i].bits, 8))
rehlds_syserror("%s: Test %i: bits not equals %p.%p|%p.%p", callsite, i, def[i].bits[0], def[i].bits[1], jit[i].bits[0], jit[i].bits[1]);
if (def[i].bytecount != jit[i].bytecount)
rehlds_syserror("%s: Test %i: bytecount not equal %i|%i", callsite, i, def[i].bytecount, jit[i].bytecount);
}
}
NOINLINE delta_t* _CreateTestDeltaDesc() {
static delta_description_t _fields[32];
delta_test_struct_t d; // "use" d variable
_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;
};
struct delta_simpletest_data_t {
const char* action;
int fill1, fill2;
bool changed;
const char* fields;
std::function<void(void)> act;
};
delta_test_struct_t dst1, dst2;
void _DeltaSimpleTest(delta_simpletest_data_t* t, delta_t* delta, int jit) {
_FillTestDelta(&dst1, t->fill1); _FillTestDelta(&dst2, t->fill2);
t->act();
_MarkAndEnsureCorrectResults(t->action, delta, &dst1, &dst2, jit, t->changed, t->fields);
}
void _DeltaSimpleTests(delta_t* delta, delta_simpletest_data_t* tests, int testsCount) {
for (int usejit = 0; usejit <= 1; usejit++) {
for (int i = 0; i < testsCount; i++) {
_DeltaSimpleTest(tests + i, delta, usejit);
}
}
}
TEST(MarkFieldsTest_Simple_Primitives, Delta, 1000) {
delta_t* delta = _CreateTestDeltaDesc();
delta_simpletest_data_t testdata[] = {
{ "SimpleUnchangedAll1", 0x71, 0x71, true, "", [](){} },
{ "SimpleUnchangedAll2", 0x71, 0x72, false, "", [](){} },
{ "Byte_0BlockCheck", 0x71, 0x71, true, "b_01", []() { dst2.b_01 = 0; } },
{ "Byte_1BlockCheck", 0x71, 0x71, true, "b_11", []() { dst2.b_11 = 0; } },
{ "Short_0BlockCheck", 0x71, 0x71, true, "s_02", []() { dst2.s_02 = 0; } },
{ "Short_1BlockCheck", 0x71, 0x71, true, "s_12", []() { dst2.s_12 = 0; } },
{ "Int_0BlockCheck", 0x71, 0x71, true, "i_04", []() { dst2.i_04 = 0; } },
{ "Int_1BlockCheck", 0x71, 0x71, true, "i_14", []() { dst2.i_14 = 0; } },
{ "Float_0BlockCheck", 0x71, 0x71, true, "f_08", []() { dst2.f_08 = 0; } },
{ "Float_1BlockCheck", 0x71, 0x71, true, "f_18", []() { dst2.f_18 = 0; } },
};
_DeltaSimpleTests(delta, testdata, ARRAYSIZE(testdata));
SV_Shutdown();
}
TEST(MarkFieldsTest_InterBlock, Delta, 1000) {
delta_t* delta = _CreateTestDeltaDesc();
delta_simpletest_data_t testdata[] = {
{ "Interblock1_guards", 0x71, 0x71, true, "b_4D b_52", []() { dst2.b_4D = dst2.b_52 = 0; } },
{ "Interblock1_guards_and_val", 0x71, 0x71, true, "b_4D b_52 i_4E", []() { dst2.b_4D = dst2.b_52 = 0; dst2.i_4E = 0; } },
{ "Interblock1_val", 0x71, 0x71, true, "i_4E", []() { dst2.i_4E = 0; } },
{ "Interblock1_val_0b", 0x71, 0x71, true, "i_4E", []() { dst2.i_4E &= 0xFFFFFF00; } },
{ "Interblock1_val_1b", 0x71, 0x71, true, "i_4E", []() { dst2.i_4E &= 0xFFFF00FF; } },
{ "Interblock1_val_2b", 0x71, 0x71, true, "i_4E", []() { dst2.i_4E &= 0xFF00FFFF; } },
{ "Interblock1_val_3b", 0x71, 0x71, true, "i_4E", []() { dst2.i_4E &= 0x00FFFFFF; } },
{ "Interblock2_guards", 0x71, 0x71, true, "b_5C b_61", []() { dst2.b_5C = dst2.b_61 = 0; } },
{ "Interblock2_guards_and_val", 0x71, 0x71, true, "b_5C b_61 i_5D", []() { dst2.b_5C = dst2.b_61 = 0; dst2.i_5D = 0; } },
{ "Interblock2_val", 0x71, 0x71, true, "i_5D", []() { dst2.i_5D = 0; } },
{ "Interblock2_val_0b", 0x71, 0x71, true, "i_5D", []() { dst2.i_5D &= 0xFFFFFF00; } },
{ "Interblock2_val_1b", 0x71, 0x71, true, "i_5D", []() { dst2.i_5D &= 0xFFFF00FF; } },
{ "Interblock2_val_2b", 0x71, 0x71, true, "i_5D", []() { dst2.i_5D &= 0xFF00FFFF; } },
{ "Interblock2_val_3b", 0x71, 0x71, true, "i_5D", []() { dst2.i_5D &= 0x00FFFFFF; } },
};
_DeltaSimpleTests(delta, testdata, ARRAYSIZE(testdata));
SV_Shutdown();
}
TEST(MarkFieldsTest_Strings, Delta, 1000) {
delta_t* delta = _CreateTestDeltaDesc();
delta_simpletest_data_t testdata[] = {
{ "Str_empty", 'c', 'c', true, "s_24", []() { dst2.s_24[0] = 0; } },
{ "Str_empty2", 'c', 'c', true, "s_24", []() { dst1.s_24[0] = 0; } },
{ "Str_both_empty_with_garbage", 'c', 'c', true, "", []() {
dst1.s_24[0] = 0; dst2.s_24[0] = 0;
dst1.s_24[1] = 'd'; dst2.s_24[1] = 'e';
}},
{ "Str_case_check", 'c', 'c', true, "", []() { dst1.s_24[0] = 'C'; } },
};
_DeltaSimpleTests(delta, testdata, ARRAYSIZE(testdata));
SV_Shutdown();
}
TEST(MarkFieldsTest_TimeWindow, Delta, 1000) {
#ifdef REHLDS_FIXES
bool rehlds_fixes = true;
#else
bool rehlds_fixes = false;
#endif
delta_t* delta = _CreateTestDeltaDesc();
delta_simpletest_data_t testdata[] = {
{ "TimeWindow_Below_Precision", 'c', 'c', true, (rehlds_fixes ? "w8_1C" : ""), []() { dst2.w8_1C = 0.001f; dst1.w8_1C = 0.0011f; } },
{ "TimeWindow_Above_Precision1", 'c', 'c', true, (rehlds_fixes ? "w8_1C" : ""), []() { dst2.w8_1C = 0.1f; dst1.w8_1C = 0.11f; } }, //precision check, 0.11f is actually 0.10999
{ "TimeWindow_Above_Precision2", 'c', 'c', true, "w8_1C", []() { dst2.w8_1C = 0.1f; dst1.w8_1C = 0.12f; } },
};
_DeltaSimpleTests(delta, testdata, ARRAYSIZE(testdata));
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;