r5sdk/r5dev/rtech/rtech.cpp
Amos d5b2e58dae Code base refactor + major performance and readability improvement. Read description for details.
* Codebase restructured to SourceSDK codebase style and .cpp/.h assertion paths in the game executable.
* Document most functions with valve style 'Purpose' blocks.
* Rename variables to match the rest of the codebase and Valve's naming convention.
* Dedicated DLL and the SDKLauncher now share the same codebase as the DevSDK.

* Obtain globals or pointers directly instead of waiting for runtime initialized data.
* Dynamically search for all functions and globals (this doesn't count for dedicated yet!).
* Initialize most in-SDK variables.

* Move certain prints and other utilities under ConVars to reduce verbosity and increase performance.
* Print all pattern scan results through a virtual function to make it easier to add and debug new patterns in the future.
* Type global var pointers appropriately if class or type is known and implemented.
* Forward declare 'CClient' class to avoid having 2 'g_pClient' copies.
* Add IDA's pseudo definitions for easier prototyping with decompiled assembly code.

* RPAK decompress Command callback implementation.
* Load decompressed RPaks from 'paks\Win32\' overriding the ones in 'paks\Win64\' (the decompress callback will automatically fix the header and write it to 'paks\Win32\').

* VPK decompress Command callback implementation.
* Move CRC32 ands Adler32 to implementation files.

* Server will print out more details about the connecting client.

* Upgrade ImGui lib to v1.86.
* Don't compile id3dx.h for dedicated.
* Don't compile id3dx.cpp for dedicated
* Implement DevMsg print function allowing to print information to the in-game VGUI/RUI console overlay, ImGui console overlay and the external windows console

* Fixed bug where the Error function would not properly terminate the process when an error is called. This caused access violations for critical/non-recoverable errors.
* Fixed bug where the game would crash if the console or server browser was enabled while the game was still starting up.
* Several bug fixes for the dedicated server (warning: dedicated is still considered work-in-progress!).
2021-12-25 22:36:38 +01:00

498 lines
14 KiB
C++

#include "core/stdafx.h"
#include "rtech/rtech.h"
#include "engine/sys_utils.h"
/******************************************************************************
-------------------------------------------------------------------------------
File : rtech.cpp
Date : 18:07:2021
Author : Kawe Mazidjatari
Purpose: Implements the 'rtech_game' core utilities
-------------------------------------------------------------------------------
History:
- 18:07:2021 | 13:02 : Created by Kawe Mazidjatari
- 10:09:2021 | 18:22 : Implement 'StringToGuid' method
- 12:11:2021 | 14:41 : Add decompression method to ConCommand callback
******************************************************************************/
//-----------------------------------------------------------------------------
// Purpose: calculate 'GUID' from input data
//-----------------------------------------------------------------------------
std::uint64_t __fastcall RTech::StringToGuid(const char* pData)
{
std::uint32_t* v1; // r8
std::uint64_t v2; // r10
int v3; // er11
std::uint32_t v4; // er9
std::uint32_t i; // edx
std::uint64_t v6; // rcx
int v7; // er9
int v8; // edx
int v9; // eax
std::uint32_t v10; // er8
int v12; // ecx
std::uint32_t* a1 = (std::uint32_t*)pData;
v1 = a1;
v2 = 0i64;
v3 = 0;
v4 = (*a1 - 45 * ((~(*a1 ^ 0x5C5C5C5Cu) >> 7) & (((*a1 ^ 0x5C5C5C5Cu) - 0x1010101) >> 7) & 0x1010101)) & 0xDFDFDFDF;
for (i = ~*a1 & (*a1 - 0x1010101) & 0x80808080; !i; i = v8 & 0x80808080)
{
v6 = v4;
v7 = v1[1];
++v1;
v3 += 4;
v2 = ((((std::uint64_t)(0xFB8C4D96501i64 * v6) >> 24) + 0x633D5F1 * v2) >> 61) ^ (((std::uint64_t)(0xFB8C4D96501i64 * v6) >> 24)
+ 0x633D5F1 * v2);
v8 = ~v7 & (v7 - 0x1010101);
v4 = (v7 - 45 * ((~(v7 ^ 0x5C5C5C5Cu) >> 7) & (((v7 ^ 0x5C5C5C5Cu) - 0x1010101) >> 7) & 0x1010101)) & 0xDFDFDFDF;
}
v9 = -1;
v10 = (i & -(signed)i) - 1;
if (_BitScanReverse((unsigned long*)&v12, v10))
{
v9 = v12;
}
return 0x633D5F1 * v2 + ((0xFB8C4D96501i64 * (std::uint64_t)(v4 & v10)) >> 24) - 0xAE502812AA7333i64 * (std::uint32_t)(v3 + v9 / 8);
}
//-----------------------------------------------------------------------------
// Purpose: calculate 'decompressed' size and commit parameters
//-----------------------------------------------------------------------------
std::uint32_t __fastcall RTech::DecompressedSize(std::int64_t param_buf, std::uint8_t* file_buf, std::int64_t file_size, std::int64_t off_no_header, std::int64_t header_size)
{
std::int64_t v8; // r9
std::uint64_t v9; // r11
char v10; // r8
int v11; // er8
std::int64_t v12; // rbx
unsigned int v13; // ebp
std::uint64_t v14; // rbx
std::int64_t v15; // rax
unsigned int v16; // er9
std::uint64_t v17; // r12
std::uint64_t v18; // r11
std::uint64_t v19; // r10
std::uint64_t v20; // rax
int v21; // ebp
std::uint64_t v22; // r10
unsigned int v23; // er9
std::int64_t v24; // rax
std::int64_t v25; // rsi
std::int64_t v26; // rdx
std::int64_t v28; // rdx
std::int64_t v29; // [rsp+48h] [rbp+18h]
std::int64_t result; // rax
v29 = 0xFFFFFFi64;
*(std::uint64_t*)param_buf = (std::uint64_t)file_buf;
*(std::uint64_t*)(param_buf + 32) = off_no_header + file_size;
*(std::uint64_t*)(param_buf + 8) = 0i64;
*(std::uint64_t*)(param_buf + 24) = 0i64;
*(std::uint32_t*)(param_buf + 68) = 0;
*(std::uint64_t*)(param_buf + 16) = -1i64;
v8 = off_no_header + header_size + 8;
v9 = *(std::uint64_t*)((0xFFFFFFi64 & (off_no_header + header_size)) + file_buf);
*(std::uint64_t*)(param_buf + 80) = header_size;
*(std::uint64_t*)(param_buf + 72) = v8;
v10 = v9;
v9 >>= 6;
v11 = v10 & 0x3F;
*(std::uint64_t*)(param_buf + 40) = (1i64 << v11) | v9 & ((1i64 << v11) - 1);
v12 = *(std::uint64_t*)((0xFFFFFFi64 & v8) + file_buf) << (64 - ((std::uint8_t)v11 + 6));
*(std::uint64_t*)(param_buf + 72) = v8 + ((std::uint8_t)(unsigned int)(v11 + 6) >> 3);
v13 = ((v11 + 6) & 7) + 13;
v14 = (0xFFFFFFFFFFFFFFFFui64 >> ((v11 + 6) & 7)) & ((v9 >> v11) | v12);
v15 = v29 & *(std::uint64_t*)(param_buf + 72);
v16 = (((std::uint8_t)v14 - 1) & 0x3F) + 1;
v17 = 0xFFFFFFFFFFFFFFFFui64 >> (64 - (std::uint8_t)v16);
*(uint64_t*)(param_buf + 48) = v17;
v18 = 0xFFFFFFFFFFFFFFFFui64 >> (64 - ((((v14 >> 6) - 1) & 0x3F) + 1));
*(uint64_t*)(param_buf + 56) = v18;
v19 = (v14 >> 13) | (*(std::uint64_t*)(v15 + file_buf) << (64 - (std::uint8_t)v13));
v20 = v13;
v21 = v13 & 7;
*(std::uint64_t*)(param_buf + 72) += v20 >> 3;
v22 = (0xFFFFFFFFFFFFFFFFui64 >> v21) & v19;
if (v17 == -1i64)
{
*(std::uint32_t*)(param_buf + 64) = 0;
*(std::uint64_t*)(param_buf + 88) = file_size;
}
else
{
v23 = v16 >> 3;
v24 = v29 & *(std::uint64_t*)(param_buf + 72);
*(std::uint32_t*)(param_buf + 64) = v23 + 1;
v25 = *(std::uint64_t*)(v24 + file_buf) & ((1i64 << (8 * ((std::uint8_t)v23 + 1))) - 1);
*(std::uint64_t*)(param_buf + 72) += v23 + 1;
*(std::uint64_t*)(param_buf + 88) = v25;
}
*(std::uint64_t*)(param_buf + 88) += off_no_header;
v26 = *(std::uint64_t*)(param_buf + 88);
*(std::uint64_t*)(param_buf + 96) = v22;
*(std::uint32_t*)(param_buf + 104) = v21;
*(std::uint64_t*)(param_buf + 112) = v17 + off_no_header - 6;
result = *(std::uint64_t*)(param_buf + 40);
*(std::uint32_t*)(param_buf + 108) = 0;
*(std::uint64_t*)(param_buf + 120) = v26;
*(std::uint64_t*)(param_buf + 128) = result;
if ((((std::uint8_t)(v14 >> 6) - 1) & 0x3F) != -1i64 && result - 1 > v18)
{
v28 = v26 - *(unsigned int*)(param_buf + 64);
*(std::uint64_t*)(param_buf + 128) = v18 + 1;
*(std::uint64_t*)(param_buf + 120) = v28;
}
return result;
}
//-----------------------------------------------------------------------------
// Purpose: decompress input data
//-----------------------------------------------------------------------------
std::uint8_t __fastcall RTech::Decompress(std::int64_t* param_buffer, std::uint64_t file_size, std::uint64_t buf_size)
{
char result; // al
std::int64_t v5; // r15
std::int64_t v6; // r11
std::uint32_t v7; // ebp
std::uint64_t v8; // rsi
std::uint64_t v9; // rdi
std::uint64_t v10; // r12
std::int64_t v11; // r13
std::uint32_t v12; // ecx
std::uint64_t v13; // rsi
std::uint64_t i; // rax
std::uint64_t v15; // r8
std::int64_t v16; // r9
int v17; // ecx
std::uint64_t v18; // rax
std::uint64_t v19; // rsi
std::int64_t v20; // r14
int v21; // ecx
std::uint64_t v22; // r11
int v23; // edx
std::int64_t v24; // rax
int v25; // er8
std::uint32_t v26; // er13
std::int64_t v27; // r10
std::int64_t v28; // rax
std::uint64_t* v29; // r10
std::uint64_t v30; // r9
std::uint64_t v31; // r10
std::uint64_t v32; // r8
std::uint64_t v33; // rax
std::uint64_t v34; // rax
std::uint64_t v35; // rax
std::uint64_t v36; // rcx
std::uint64_t v37; // rdx
std::uint64_t v38; // r14
std::uint64_t v39; // r11
char v40; // cl
std::uint64_t v41; // rsi
std::uint64_t v42; // rcx
std::uint64_t v43; // r8
int v44; // er11
std::uint8_t v45; // r9
std::uint64_t v46; // rcx
std::uint64_t v47; // rcx
std::uint64_t v48; // r9
std::uint64_t l; // r8
std::uint32_t v50; // er9
std::uint64_t v51; // r8
std::uint64_t v52; // rdx
std::uint64_t k; // r8
char* v54; // r10
std::uint64_t v55; // rdx
std::uint32_t v56; // er14
std::uint64_t* v57; // rdx
std::uint64_t* v58; // r8
char v59; // al
std::uint64_t v60; // rsi
std::uint64_t v61; // rax
std::uint64_t v62; // r9
int v63; // er10
std::uint8_t v64; // cl
std::uint64_t v65; // rax
std::uint32_t v66; // er14
std::uint32_t j; // ecx
std::uint64_t v68; // rax
std::uint64_t v69; // rcx
std::uint64_t v70; // [rsp+0h] [rbp-58h]
int v71; // [rsp+60h] [rbp+8h]
std::uint64_t v74; // [rsp+78h] [rbp+20h]
if (file_size < param_buffer[11])
{
return 0;
}
v5 = param_buffer[10];
if (buf_size < param_buffer[7] + (v5 & (std::uint64_t)~param_buffer[7]) + 1 && buf_size < param_buffer[5])
{
return 0;
}
v6 = param_buffer[1];
v7 = *((std::uint32_t*)param_buffer + 26);
v8 = param_buffer[12];
v9 = param_buffer[9];
v10 = param_buffer[14];
v11 = *param_buffer;
if (param_buffer[15] < v10)
{
v10 = param_buffer[15];
}
v12 = *((std::uint32_t*)param_buffer + 27);
v74 = v11;
v70 = v6;
v71 = v12;
if (!v7)
{
goto LABEL_11;
}
v13 = (*(std::uint64_t*)((v9 & param_buffer[2]) + v11) << (64 - (std::uint8_t)v7)) | v8;
for (i = v7; ; i = v7)
{
v7 &= 7u;
v9 += i >> 3;
v12 = v71;
v8 = (0xFFFFFFFFFFFFFFFFui64 >> v7) & v13;
LABEL_11:
v15 = (std::uint64_t)v12 << 8;
v16 = v12;
v17 = *((std::uint8_t*)&LUT_0 + (std::uint8_t)v8 + v15 + 512);
v18 = (std::uint8_t)v8 + v15;
v7 += v17;
v19 = v8 >> v17;
v20 = (std::uint32_t)*((char*)&LUT_0 + v18);
if (*((char*)&LUT_0 + v18) < 0)
{
v56 = -(int)v20;
v57 = (std::uint64_t*)(v11 + (v9 & param_buffer[2]));
v71 = 1;
v58 = (std::uint64_t*)(v6 + (v5 & param_buffer[3]));
if (v56 == *((std::uint8_t*)&LUT_0 + v16 + 1248))
{
if ((~v9 & param_buffer[6]) < 0xF || (param_buffer[7] & (std::uint64_t)~v5) < 0xF || (std::uint64_t)(param_buffer[5] - v5) < 0x10)
{
v56 = 1;
}
v59 = v19;
v60 = v19 >> 3;
v61 = v59 & 7;
v62 = v60;
if (v61)
{
v63 = *((std::uint8_t*)&LUT_0 + v61 + 1232);
v64 = *((std::uint8_t*)&LUT_0 + v61 + 1240);
}
else
{
v62 = v60 >> 4;
v65 = v60 & 0xF;
v7 += 4;
v63 = *((std::uint32_t*)&LUT_0 + v65 + 288);
v64 = *((std::uint8_t*)&LUT_0 + v65 + 1216);
}
v7 += v64 + 3;
v19 = v62 >> v64;
v66 = v63 + (v62 & ((1 << v64) - 1)) + v56;
for (j = v66 >> 3; j; --j)
{
v68 = *v57++;
*v58++ = v68;
}
if ((v66 & 4) != 0)
{
*(std::uint32_t*)v58 = *(std::uint32_t*)v57;
v58 = (std::uint64_t*)((char*)v58 + 4);
v57 = (std::uint64_t*)((char*)v57 + 4);
}
if ((v66 & 2) != 0)
{
*(std::uint16_t*)v58 = *(std::uint16_t*)v57;
v58 = (std::uint64_t*)((char*)v58 + 2);
v57 = (std::uint64_t*)((char*)v57 + 2);
}
if ((v66 & 1) != 0)
{
*(std::uint8_t*)v58 = *(std::uint8_t*)v57;
}
v9 += v66;
v5 += v66;
}
else
{
*v58 = *v57;
v58[1] = v57[1];
v9 += v56;
v5 += v56;
}
}
else
{
v21 = v19 & 0xF;
v71 = 0;
v22 = ((std::uint64_t)(std::uint32_t)v19 >> (((std::uint32_t)(v21 - 31) >> 3) & 6)) & 0x3F;
v23 = 1 << (v21 + ((v19 >> 4) & ((24 * (((std::uint32_t)(v21 - 31) >> 3) & 2)) >> 4)));
v7 += (((std::uint32_t)(v21 - 31) >> 3) & 6) + *((std::uint8_t*)&LUT_0 + v22 + 1088) + v21 + ((v19 >> 4) & ((24 * (((std::uint32_t)(v21 - 31) >> 3) & 2)) >> 4));
v24 = param_buffer[3];
v25 = 16 * (v23 + ((v23 - 1) & (v19 >> ((((std::uint32_t)(v21 - 31) >> 3) & 6) + *((std::uint8_t*)&LUT_0 + v22 + 1088)))));
v19 >>= (((std::uint32_t)(v21 - 31) >> 3) & 6) + *((std::uint8_t*)&LUT_0 + v22 + 1088) + v21 + ((v19 >> 4) & ((24 * (((std::uint32_t)(v21 - 31) >> 3) & 2)) >> 4));
v26 = v25 + *((std::uint8_t*)&LUT_0 + v22 + 1024) - 16;
v27 = v24 & (v5 - v26);
v28 = v70 + (v5 & v24);
v29 = (std::uint64_t*)(v70 + v27);
if ((std::uint32_t)v20 == 17)
{
v40 = v19;
v41 = v19 >> 3;
v42 = v40 & 7;
v43 = v41;
if (v42)
{
v44 = *((std::uint8_t*)&LUT_0 + v42 + 1232);
v45 = *((std::uint8_t*)&LUT_0 + v42 + 1240);
}
else
{
v7 += 4;
v46 = v41 & 0xF;
v43 = v41 >> 4;
v44 = *((std::uint32_t*)&LUT_0 + v46 + 288);
v45 = *((std::uint8_t*)&LUT_0 + v46 + 1216);
if (v74 && v7 + v45 >= 0x3D)
{
v47 = v9++ & param_buffer[2];
v43 |= (std::uint64_t)*(std::uint8_t*)(v47 + v74) << (61 - (std::uint8_t)v7);
v7 -= 8;
}
}
v7 += v45 + 3;
v19 = v43 >> v45;
v48 = ((std::uint32_t)v43 & ((1 << v45) - 1)) + v44 + 17;
v5 += v48;
if (v26 < 8)
{
v50 = v48 - 13;
v5 -= 13i64;
if (v26 == 1)
{
v51 = *(std::uint8_t*)v29;
v52 = 0i64;
for (k = 0x101010101010101i64 * v51; (std::uint32_t)v52 < v50; v52 = (std::uint32_t)(v52 + 8))
{
*(std::uint64_t*)(v52 + v28) = k;
}
}
else
{
if (v50)
{
v54 = (char*)v29 - v28;
v55 = v50;
do
{
*(std::uint8_t*)v28 = v54[v28];
++v28;
--v55;
} while (v55);
}
}
}
else
{
for (l = 0i64; (std::uint32_t)l < (std::uint32_t)v48; l = (std::uint32_t)(l + 8))
{
*(std::uint64_t*)(l + v28) = *(std::uint64_t*)((char*)v29 + l);
}
}
}
else
{
v5 += v20;
*(std::uint64_t*)v28 = *v29;
*(std::uint64_t*)(v28 + 8) = v29[1];
}
v11 = v74;
}
if (v9 >= v10)
{
break;
}
LABEL_29:
v6 = v70;
v13 = (*(std::uint64_t*)((v9 & param_buffer[2]) + v11) << (64 - (std::uint8_t)v7)) | v19;
}
if (v5 != param_buffer[16])
{
goto LABEL_25;
}
v30 = param_buffer[5];
if (v5 == v30)
{
result = 1;
goto LABEL_69;
}
v31 = param_buffer[6];
v32 = *((std::uint32_t*)param_buffer + 16);
v33 = v31 & -(std::int64_t)v9;
v19 >>= 1;
++v7;
if (v32 > v33)
{
v9 += v33;
v34 = param_buffer[14];
if (v9 > v34)
{
param_buffer[14] = v31 + v34 + 1;
}
}
v35 = v9 & param_buffer[2];
v9 += v32;
v36 = v5 + param_buffer[7] + 1;
v37 = *(std::uint32_t*)(v35 + v11) & ((1i64 << (8 * (std::uint8_t)v32)) - 1);
v38 = v37 + param_buffer[11];
v39 = v37 + param_buffer[15];
param_buffer[11] = v38;
param_buffer[15] = v39;
if (v36 >= v30)
{
v36 = v30;
param_buffer[15] = v32 + v39;
}
param_buffer[16] = v36;
if (file_size >= v38 && buf_size >= v36)
{
LABEL_25:
v10 = param_buffer[14];
if (v9 >= v10)
{
v9 = ~param_buffer[6] & (v9 + 7);
v10 += param_buffer[6] + 1;
param_buffer[14] = v10;
}
if (param_buffer[15] < v10)
{
v10 = param_buffer[15];
}
goto LABEL_29;
}
v69 = param_buffer[14];
if (v9 >= v69)
{
v9 = ~v31 & (v9 + 7);
param_buffer[14] = v69 + v31 + 1;
}
*((std::uint32_t*)param_buffer + 27) = v71;
result = 0;
param_buffer[12] = v19;
*((std::uint32_t*)param_buffer + 26) = v7;
LABEL_69:
param_buffer[10] = v5;
param_buffer[9] = v9;
return result;
}
///////////////////////////////////////////////////////////////////////////////
RTech* g_pRtech = new RTech();