#include "core/stdafx.h"
#include "tier1/cvar.h"
#include "rtech/rtech_utils.h"
#ifndef DEDICATED
#include "windows/id3dx.h"
#include "materialsystem/cshaderglue.h"
#include "public/rendersystem/schema/texture.g.h"
#endif // !DEDICATED

/******************************************************************************
-------------------------------------------------------------------------------
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
- 25:12:2021 | 23:20 : Made everything more readable thanks to bezdna5-rs
- 28:03:2022 | 18:00 : Added getting pak info by PakID.

******************************************************************************/

//-----------------------------------------------------------------------------
// Purpose: calculate 'GUID' from input data
//-----------------------------------------------------------------------------
uint64_t __fastcall RTech::StringToGuid(const char* pData)
{
	uint32_t*        v1; // r8
	uint64_t         v2; // r10
	int32_t          v3; // er11
	uint32_t         v4; // er9
	uint32_t          i; // edx
	uint64_t         v6; // rcx
	int32_t          v7; // er9
	int32_t          v8; // edx
	int32_t          v9; // eax
	uint32_t        v10; // er8
	int32_t         v12; // ecx
	uint32_t* a1 = (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 = ((((uint64_t)(0xFB8C4D96501i64 * v6) >> 24) + 0x633D5F1 * v2) >> 61) ^ (((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 * (uint64_t)(v4 & v10)) >> 24) - 0xAE502812AA7333i64 * (uint32_t)(v3 + v9 / 8);
}

//-----------------------------------------------------------------------------
// Purpose: calculate 'decompressed' size and commit parameters
//-----------------------------------------------------------------------------
uint64_t __fastcall RTech::DecompressPakFileInit(PakDecompState_t* state, uint8_t* fileBuffer, uint64_t fileSize, uint64_t offNoHeader, uint64_t headerSize)
{
	int64_t input_byte_pos_init;         // r9
	uint64_t byte_init;                  // r11
	int32_t decompressed_size_bits;      // ecx
	int64_t byte_1_low;                  // rdi
	uint64_t input_byte_pos_1;           // r10
	uint32_t bit_pos_final;              // ebp
	uint64_t byte_1;                     // rdi
	uint32_t brih_bits;                  // er11
	uint64_t inv_mask_in;                // r8
	uint64_t byte_final_full;            // rbx
	uint64_t bit_pos_final_1;            // rax
	int32_t byte_bit_offset_final;       // ebp
	uint64_t input_byte_pos_final;       // r10
	uint64_t byte_final;                 // rbx
	uint32_t brih_bytes;                 // er11
	uint64_t byte_tmp;                   // rdx
	uint64_t stream_len_needed;          // r14
	uint64_t result;                     // rax
	uint64_t inv_mask_out;               // r8
	uint64_t qw70;                       // rcx
	uint64_t stream_compressed_size_new; // rdx

	const uintptr_t mask = UINT64_MAX;
	const uintptr_t file_buf = uintptr_t(fileBuffer);

	state->m_inputBuf = file_buf;
	state->m_outputBuf = 0i64;
	state->m_outputMask = 0i64;
	state->dword44 = 0;
	state->m_fileSize = fileSize + offNoHeader;
	state->m_inputMask = mask;
	input_byte_pos_init = offNoHeader + headerSize + 8;
	byte_init = *(uint64_t*)((mask & (offNoHeader + headerSize)) + file_buf);
	state->m_decompBytePosition = headerSize;
	decompressed_size_bits = byte_init & 0x3F;
	byte_init >>= 6;
	state->m_fileBytePosition = input_byte_pos_init;
	state->m_decompSize = (byte_init & ((1i64 << decompressed_size_bits) - 1)) | (1i64 << decompressed_size_bits);
	byte_1_low = *(uint64_t*)((mask & input_byte_pos_init) + file_buf) << (64
		- ((uint8_t)decompressed_size_bits
			+ 6));
	input_byte_pos_1 = input_byte_pos_init + ((uint64_t)(uint32_t)(decompressed_size_bits + 6) >> 3);
	state->m_fileBytePosition = input_byte_pos_1;
	bit_pos_final = ((decompressed_size_bits + 6) & 7) + 13;
	byte_1 = (0xFFFFFFFFFFFFFFFFui64 >> ((decompressed_size_bits + 6) & 7)) & ((byte_init >> decompressed_size_bits) | byte_1_low);
	brih_bits = (((uint8_t)byte_1 - 1) & 0x3F) + 1;
	inv_mask_in = 0xFFFFFFFFFFFFFFFFui64 >> (64 - (uint8_t)brih_bits);
	state->m_inputInvMask = inv_mask_in;
	state->m_outputInvMask = 0xFFFFFFFFFFFFFFFFui64 >> (63 - (((byte_1 >> 6) - 1) & 0x3F));
	byte_final_full = (byte_1 >> 13) | (*(uint64_t*)((mask & input_byte_pos_1) + file_buf) << (64
		- (uint8_t)bit_pos_final));
	bit_pos_final_1 = bit_pos_final;
	byte_bit_offset_final = bit_pos_final & 7;
	input_byte_pos_final = (bit_pos_final_1 >> 3) + input_byte_pos_1;
	byte_final = (0xFFFFFFFFFFFFFFFFui64 >> byte_bit_offset_final) & byte_final_full;
	state->m_fileBytePosition = input_byte_pos_final;
	if (inv_mask_in == -1i64)
	{
		state->m_headerOffset = 0;
		stream_len_needed = fileSize;
	}
	else
	{
		brih_bytes = brih_bits >> 3;
		state->m_headerOffset = brih_bytes + 1;
		byte_tmp = *(uint64_t*)((mask & input_byte_pos_final) + file_buf);
		state->m_fileBytePosition = input_byte_pos_final + brih_bytes + 1;
		stream_len_needed = byte_tmp & ((1i64 << (8 * ((uint8_t)brih_bytes + 1))) - 1);
	}
	result = state->m_decompSize;
	inv_mask_out = state->m_outputInvMask;
	qw70 = offNoHeader + state->m_inputInvMask - 6i64;
	state->m_bufferSizeNeeded = stream_len_needed + offNoHeader;
	state->qword70 = qw70;
	state->m_currentByte = byte_final;
	state->m_currentByteBit = byte_bit_offset_final;
	state->dword6C = 0;
	state->m_compressedStreamSize = stream_len_needed + offNoHeader;
	state->m_decompStreamSize = result;
	if (result - 1 > inv_mask_out)
	{
		stream_compressed_size_new = stream_len_needed + offNoHeader - state->m_headerOffset;
		state->m_decompStreamSize = inv_mask_out + 1;
		state->m_compressedStreamSize = stream_compressed_size_new;
	}

	return result;
}

static const unsigned char /*unk_141313180*/ s_PakFileCompressionLUT[0x720] =
{
	0x04, 0xFE, 0xFC, 0x08, 0x04, 0xEF, 0x11, 0xF9, 0x04, 0xFD, 0xFC, 0x07, 0x04, 0x05, 0xFF, 0xF4,
	0x04, 0xFE, 0xFC, 0x10, 0x04, 0xEF, 0x11, 0xF6, 0x04, 0xFD, 0xFC, 0xFB, 0x04, 0x06, 0xFF, 0x0B,
	0x04, 0xFE, 0xFC, 0x08, 0x04, 0xEF, 0x11, 0xF8, 0x04, 0xFD, 0xFC, 0x0C, 0x04, 0x05, 0xFF, 0xF7,
	0x04, 0xFE, 0xFC, 0x10, 0x04, 0xEF, 0x11, 0xF5, 0x04, 0xFD, 0xFC, 0xFA, 0x04, 0x06, 0xFF, 0xF3,
	0x04, 0xFE, 0xFC, 0x08, 0x04, 0xEF, 0x11, 0xF9, 0x04, 0xFD, 0xFC, 0x07, 0x04, 0x05, 0xFF, 0xF4,
	0x04, 0xFE, 0xFC, 0x10, 0x04, 0xEF, 0x11, 0xF6, 0x04, 0xFD, 0xFC, 0xFB, 0x04, 0x06, 0xFF, 0x0E,
	0x04, 0xFE, 0xFC, 0x08, 0x04, 0xEF, 0x11, 0xF8, 0x04, 0xFD, 0xFC, 0x0C, 0x04, 0x05, 0xFF, 0x09,
	0x04, 0xFE, 0xFC, 0x10, 0x04, 0xEF, 0x11, 0xF5, 0x04, 0xFD, 0xFC, 0xFA, 0x04, 0x06, 0xFF, 0xF1,
	0x04, 0xFE, 0xFC, 0x08, 0x04, 0xEF, 0x11, 0xF9, 0x04, 0xFD, 0xFC, 0x07, 0x04, 0x05, 0xFF, 0xF4,
	0x04, 0xFE, 0xFC, 0x10, 0x04, 0xEF, 0x11, 0xF6, 0x04, 0xFD, 0xFC, 0xFB, 0x04, 0x06, 0xFF, 0x0D,
	0x04, 0xFE, 0xFC, 0x08, 0x04, 0xEF, 0x11, 0xF8, 0x04, 0xFD, 0xFC, 0x0C, 0x04, 0x05, 0xFF, 0xF7,
	0x04, 0xFE, 0xFC, 0x10, 0x04, 0xEF, 0x11, 0xF5, 0x04, 0xFD, 0xFC, 0xFA, 0x04, 0x06, 0xFF, 0xF2,
	0x04, 0xFE, 0xFC, 0x08, 0x04, 0xEF, 0x11, 0xF9, 0x04, 0xFD, 0xFC, 0x07, 0x04, 0x05, 0xFF, 0xF4,
	0x04, 0xFE, 0xFC, 0x10, 0x04, 0xEF, 0x11, 0xF6, 0x04, 0xFD, 0xFC, 0xFB, 0x04, 0x06, 0xFF, 0x0F,
	0x04, 0xFE, 0xFC, 0x08, 0x04, 0xEF, 0x11, 0xF8, 0x04, 0xFD, 0xFC, 0x0C, 0x04, 0x05, 0xFF, 0x0A,
	0x04, 0xFE, 0xFC, 0x10, 0x04, 0xEF, 0x11, 0xF5, 0x04, 0xFD, 0xFC, 0xFA, 0x04, 0x06, 0xFF, 0xF0,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x07, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x11,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x08, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x0C,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x07, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x09,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x08, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x0E,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x07, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x11,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x08, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x0B,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x07, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x0A,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x08, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x10,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x07, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x11,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x08, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x0C,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x07, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x09,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x08, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x0F,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x07, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x11,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x08, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x0D,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x07, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x0A,
	0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0x08, 0x04, 0x05, 0x04, 0x06, 0x04, 0x05, 0x04, 0xFF,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x06,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x08,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x07,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x08,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x06,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x08,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x08,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x08,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x06,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x08,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x07,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x08,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x06,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x08,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x08,
	0x02, 0x04, 0x03, 0x05, 0x02, 0x04, 0x04, 0x06, 0x02, 0x04, 0x03, 0x06, 0x02, 0x05, 0x04, 0x08,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x06,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x07,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x07,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x08,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x06,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x08,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x07,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x08,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x06,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x07,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x07,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x08,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x06,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x08,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x07,
	0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x03, 0x01, 0x02, 0x01, 0x08,
	0x00, 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x06, 0x00, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x0B,
	0x00, 0x08, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x09, 0x00, 0x08, 0x00, 0x03, 0x00, 0x08, 0x00, 0x0E,
	0x00, 0x08, 0x00, 0x04, 0x00, 0x08, 0x00, 0x07, 0x00, 0x08, 0x00, 0x02, 0x00, 0x08, 0x00, 0x0D,
	0x00, 0x08, 0x00, 0x0C, 0x00, 0x08, 0x00, 0x0A, 0x00, 0x08, 0x00, 0x05, 0x00, 0x08, 0x00, 0x0F,
	0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x06, 0x01, 0x02, 0x01, 0x06, 0x01, 0x02, 0x01, 0x06,
	0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x06, 0x01, 0x02, 0x01, 0x06, 0x01, 0x02, 0x01, 0x06,
	0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x06, 0x01, 0x02, 0x01, 0x06, 0x01, 0x02, 0x01, 0x06,
	0x01, 0x02, 0x01, 0x05, 0x01, 0x02, 0x01, 0x06, 0x01, 0x02, 0x01, 0x06, 0x01, 0x02, 0x01, 0x06,
	0x4A, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0xAA, 0x00, 0x00, 0x00,
	0xCA, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x00, 0x00, 0x2A, 0x01, 0x00, 0x00,
	0x4A, 0x01, 0x00, 0x00, 0x6A, 0x01, 0x00, 0x00, 0x8A, 0x01, 0x00, 0x00, 0xAA, 0x01, 0x00, 0x00,
	0xAA, 0x03, 0x00, 0x00, 0xAA, 0x05, 0x00, 0x00, 0xAA, 0x25, 0x00, 0x00, 0xAA, 0x25, 0x02, 0x00,
	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x09, 0x09, 0x0D, 0x11, 0x15,
	0x00, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x2A, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05,
	0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xBF,
	0xA8, 0xAA, 0x2A, 0xBE, 0xA8, 0xAA, 0x2A, 0xBE, 0xA8, 0xAA, 0x2A, 0xBE, 0xA8, 0xAA, 0x2A, 0xBE,
	0xD2, 0x85, 0x08, 0x3C, 0xD2, 0x85, 0x08, 0x3C, 0xD2, 0x85, 0x08, 0x3C, 0xD2, 0x85, 0x08, 0x3C,
	0x83, 0xF9, 0x22, 0x3F, 0x83, 0xF9, 0x22, 0x3F, 0x83, 0xF9, 0x22, 0x3F, 0x83, 0xF9, 0x22, 0x3F,
	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
	0x00, 0x10, 0xC9, 0x3F, 0x00, 0x10, 0xC9, 0x3F, 0x00, 0x10, 0xC9, 0x3F, 0x00, 0x10, 0xC9, 0x3F,
	0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F,
	0x02, 0x61, 0x4D, 0xB9, 0x02, 0x61, 0x4D, 0xB9, 0x02, 0x61, 0x4D, 0xB9, 0x02, 0x61, 0x4D, 0xB9,
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
	0xC2, 0x14, 0xCF, 0x37, 0xC2, 0x14, 0xCF, 0x37, 0xC2, 0x14, 0xCF, 0x37, 0xC2, 0x14, 0xCF, 0x37,
	0x9E, 0x4B, 0x6F, 0xB0, 0x9E, 0x4B, 0x6F, 0xB0, 0x9E, 0x4B, 0x6F, 0xB0, 0x9E, 0x4B, 0x6F, 0xB0,
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
	0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xF1, 0x1D, 0xC1, 0xF6, 0x7F, 0x00, 0x00,
	0x22, 0x0B, 0xB6, 0xBA, 0x22, 0x0B, 0xB6, 0xBA, 0x22, 0x0B, 0xB6, 0xBA, 0x22, 0x0B, 0xB6, 0xBA,
	0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F,
	0x02, 0x61, 0x4D, 0xB9, 0x02, 0x61, 0x4D, 0xB9, 0x02, 0x61, 0x4D, 0xB9, 0x02, 0x61, 0x4D, 0xB9,
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
	0xC2, 0x14, 0xCF, 0x37, 0xC2, 0x14, 0xCF, 0x37, 0xC2, 0x14, 0xCF, 0x37, 0xC2, 0x14, 0xCF, 0x37,
	0x9E, 0x4B, 0x6F, 0xB0, 0x9E, 0x4B, 0x6F, 0xB0, 0x9E, 0x4B, 0x6F, 0xB0, 0x9E, 0x4B, 0x6F, 0xB0,
	0x22, 0x0B, 0xB6, 0xBA, 0x22, 0x0B, 0xB6, 0xBA, 0x22, 0x0B, 0xB6, 0xBA, 0x22, 0x0B, 0xB6, 0xBA,
	0x00, 0x70, 0x95, 0xB6, 0x00, 0x70, 0x95, 0xB6, 0x00, 0x70, 0x95, 0xB6, 0x00, 0x70, 0x95, 0xB6,
	0xA9, 0xAA, 0x2A, 0x3D, 0xA9, 0xAA, 0x2A, 0x3D, 0xA9, 0xAA, 0x2A, 0x3D, 0xA9, 0xAA, 0x2A, 0x3D,
	0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x80, 0x3F,
	0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00, 0x00, 0xBF,
	0xA8, 0xAA, 0x2A, 0xBE, 0xA8, 0xAA, 0x2A, 0xBE, 0xA8, 0xAA, 0x2A, 0xBE, 0xA8, 0xAA, 0x2A, 0xBE,
	0xD2, 0x85, 0x08, 0x3C, 0xD2, 0x85, 0x08, 0x3C, 0xD2, 0x85, 0x08, 0x3C, 0xD2, 0x85, 0x08, 0x3C,
	0x83, 0xF9, 0x22, 0x3F, 0x83, 0xF9, 0x22, 0x3F, 0x83, 0xF9, 0x22, 0x3F, 0x83, 0xF9, 0x22, 0x3F,
	0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
	0x00, 0x10, 0xC9, 0x3F, 0x00, 0x10, 0xC9, 0x3F, 0x00, 0x10, 0xC9, 0x3F, 0x00, 0x10, 0xC9, 0x3F,
	0x4C, 0x39, 0x56, 0x75, 0x42, 0x52, 0x65, 0x75, 0x70, 0x35, 0x31, 0x77, 0x4C, 0x51, 0x64, 0x61,
};

//-----------------------------------------------------------------------------
// Purpose: decompress input data
//-----------------------------------------------------------------------------
uint8_t __fastcall RTech::DecompressPakFile(PakDecompState_t* state, uint64_t inLen, uint64_t outLen)
{
	char result;                          // al
	uint64_t v5;                          // r15
	uint64_t v6;                          // r11
	uint32_t v7;                          // ebp
	uint64_t v8;                          // rsi
	uint64_t v9;                          // rdi
	uint64_t v10;                         // r12
	uint64_t v11;                         // r13
	uint32_t v12;                         // ecx
	uint64_t v13;                         // rsi
	uint64_t i;                           // rax
	uint64_t v15;                         // r8
	int64_t v16;                          // r9
	int v17;                              // ecx
	uint64_t v18;                         // rax
	uint64_t v19;                         // rsi
	int64_t v20;                          // r14
	int v21;                              // ecx
	uint64_t v22;                         // r11
	int v23;                              // edx
	uint64_t v24;                         // rax
	int v25;                              // er8
	uint32_t v26;                         // er13
	uint64_t v27;                         // r10
	uint64_t v28;                         // rax
	_QWORD* v29;                          // r10
	uint64_t v30;                         // r9
	uint64_t v31;                         // r10
	uint64_t v32;                         // r8
	uint64_t v33;                         // rax
	uint64_t v34;                         // rax
	uint64_t v35;                         // rax
	uint64_t v36;                         // rcx
	int64_t v37;                          // rdx
	uint64_t v38;                         // r14
	uint64_t v39;                         // r11
	char v40;                             // cl
	uint64_t v41;                         // rsi
	int64_t v42;                          // rcx
	uint64_t v43;                         // r8
	int v44;                              // er11
	uint8_t v45;                          // r9
	uint64_t v46;                         // rcx
	uint64_t v47;                         // rcx
	int64_t v48;                          // r9
	int64_t l;                            // r8
	uint32_t v50;                         // er9
	int64_t v51;                          // r8
	int64_t v52;                          // rdx
	int64_t k;                            // r8
	char* v54;                            // r10
	int64_t v55;                          // rdx
	uint32_t v56;                         // er14
	int64_t* v57;                         // rdx
	int64_t* v58;                         // r8
	char v59;                             // al
	uint64_t v60;                         // rsi
	int64_t v61;                          // rax
	uint64_t v62;                         // r9
	int v63;                              // er10
	uint8_t v64;                          // cl
	uint64_t v65;                         // rax
	uint32_t v66;                         // er14
	uint32_t j;                           // ecx
	int64_t v68;                          // rax
	uint64_t v69;                         // rcx
	uint64_t v70;                         // [rsp+0h] [rbp-58h]
	uint32_t v71;                         // [rsp+60h] [rbp+8h]
	uint64_t v74;                         // [rsp+78h] [rbp+20h]

	if (inLen < state->m_bufferSizeNeeded)
		return 0;
	v5 = state->m_decompBytePosition;
	if (outLen < state->m_outputInvMask + (v5 & ~state->m_outputInvMask) + 1 && outLen < state->m_decompSize)
		return 0;
	v6 = state->m_outputBuf;
	v7 = state->m_currentByteBit;
	v8 = state->m_currentByte;
	v9 = state->m_fileBytePosition;
	v10 = state->qword70;
	v11 = state->m_inputBuf;
	if (state->m_compressedStreamSize < v10)
		v10 = state->m_compressedStreamSize;
	v12 = state->dword6C;
	v74 = v11;
	v70 = v6;
	v71 = v12;
	if (!v7)
		goto LABEL_11;
	v13 = (*(_QWORD*)((v9 & state->m_inputMask) + v11) << (64 - (unsigned __int8)v7)) | v8;
	for (i = v7; ; i = v7)
	{
		v7 &= 7u;
		v9 += i >> 3;
		v12 = v71;
		v8 = (0xFFFFFFFFFFFFFFFFui64 >> v7) & v13;
	LABEL_11:
		v15 = (unsigned __int64)v12 << 8;
		v16 = v12;
		v17 = *((unsigned __int8*)&s_PakFileCompressionLUT + (unsigned __int8)v8 + v15 + 512);
		v18 = (unsigned __int8)v8 + v15;
		v7 += v17;
		v19 = v8 >> v17;
		v20 = (unsigned int)*((char*)&s_PakFileCompressionLUT + v18);
		if (*((char*)&s_PakFileCompressionLUT + v18) < 0)
		{
			v56 = -(int)v20;
			v57 = (__int64*)(v11 + (v9 & state->m_inputMask));
			v71 = 1;
			v58 = (__int64*)(v6 + (v5 & state->m_outputMask));
			if (v56 == *((unsigned __int8*)&s_PakFileCompressionLUT + v16 + 1248))
			{
				if ((~v9 & state->m_inputInvMask) < 0xF || (state->m_outputInvMask & ~v5) < 15 || state->m_decompSize - v5 < 0x10)
					v56 = 1;
				v59 = char(v19);
				v60 = v19 >> 3;
				v61 = v59 & 7;
				v62 = v60;
				if (v61)
				{
					v63 = *((unsigned __int8*)&s_PakFileCompressionLUT + v61 + 1232);
					v64 = *((_BYTE*)&s_PakFileCompressionLUT + v61 + 1240);
				}
				else
				{
					v62 = v60 >> 4;
					v65 = v60 & 0xF;
					v7 += 4;
					v63 = *((_DWORD*)&s_PakFileCompressionLUT + v65 + 288);
					v64 = *((_BYTE*)&s_PakFileCompressionLUT + 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)
				{
					*(_DWORD*)v58 = *(_DWORD*)v57;
					v58 = (__int64*)((char*)v58 + 4);
					v57 = (__int64*)((char*)v57 + 4);
				}
				if ((v66 & 2) != 0)
				{
					*(_WORD*)v58 = *(_WORD*)v57;
					v58 = (__int64*)((char*)v58 + 2);
					v57 = (__int64*)((char*)v57 + 2);
				}
				if ((v66 & 1) != 0)
					*(_BYTE*)v58 = *(_BYTE*)v57;
				v9 += v66;
				v5 += v66;
			}
			else
			{
				*v58 = *v57;
				v58[1] = v57[1];
				v9 += v56;
				v5 += v56;
			}
		}
		else
		{
			v21 = v19 & 0xF;
			v71 = 0;
			v22 = ((unsigned __int64)(unsigned int)v19 >> (((unsigned int)(v21 - 31) >> 3) & 6)) & 0x3F;
			v23 = 1 << (v21 + ((v19 >> 4) & ((24 * (((unsigned int)(v21 - 31) >> 3) & 2)) >> 4)));
			v7 += (((unsigned int)(v21 - 31) >> 3) & 6) + *((unsigned __int8*)&s_PakFileCompressionLUT + v22 + 1088) + v21 + ((v19 >> 4) & ((24 * (((unsigned int)(v21 - 31) >> 3) & 2)) >> 4));
			v24 = state->m_outputMask;
			v25 = 16 * (v23 + ((v23 - 1) & (v19 >> ((((unsigned int)(v21 - 31) >> 3) & 6) + *((_BYTE*)&s_PakFileCompressionLUT + v22 + 1088)))));
			v19 >>= (((unsigned int)(v21 - 31) >> 3) & 6) + *((_BYTE*)&s_PakFileCompressionLUT + v22 + 1088) + v21 + ((v19 >> 4) & ((24 * (((unsigned int)(v21 - 31) >> 3) & 2)) >> 4));
			v26 = v25 + *((unsigned __int8*)&s_PakFileCompressionLUT + v22 + 1024) - 16;
			v27 = v24 & (v5 - v26);
			v28 = v70 + (v5 & v24);
			v29 = (_QWORD*)(v70 + v27);
			if ((_DWORD)v20 == 17)
			{
				v40 = char(v19);
				v41 = v19 >> 3;
				v42 = v40 & 7;
				v43 = v41;
				if (v42)
				{
					v44 = *((unsigned __int8*)&s_PakFileCompressionLUT + v42 + 1232);
					v45 = *((_BYTE*)&s_PakFileCompressionLUT + v42 + 1240);
				}
				else
				{
					v7 += 4;
					v46 = v41 & 0xF;
					v43 = v41 >> 4;
					v44 = *((_DWORD*)&s_PakFileCompressionLUT + v46 + 288);
					v45 = *((_BYTE*)&s_PakFileCompressionLUT + v46 + 1216);
					if (v74 && v7 + v45 >= 61)
					{
						v47 = v9++ & state->m_inputMask;
						v43 |= (unsigned __int64)*(unsigned __int8*)(v47 + v74) << (61 - (unsigned __int8)v7);
						v7 -= 8;
					}
				}
				v7 += v45 + 3;
				v19 = v43 >> v45;
				v48 = ((unsigned int)v43 & ((1 << v45) - 1)) + v44 + 17;
				v5 += v48;
				if (v26 < 8)
				{
					v50 = uint32_t(v48 - 13);
					v5 -= 13i64;
					if (v26 == 1)
					{
						v51 = *(unsigned __int8*)v29;
						//++dword_14D40B2BC;
						v52 = 0i64;
						for (k = 0x101010101010101i64 * v51; (unsigned int)v52 < v50; v52 = (unsigned int)(v52 + 8))
							*(_QWORD*)(v52 + v28) = k;
					}
					else
					{
						//++dword_14D40B2B8;
						if (v50)
						{
							v54 = (char*)v29 - v28;
							v55 = v50;
							do
							{
								*(_BYTE*)v28 = v54[v28];
								++v28;
								--v55;
							} while (v55);
						}
					}
				}
				else
				{
					//++dword_14D40B2AC;
					for (l = 0i64; (unsigned int)l < (unsigned int)v48; l = (unsigned int)(l + 8))
						*(_QWORD*)(l + v28) = *(_QWORD*)((char*)v29 + l);
				}
			}
			else
			{
				v5 += v20;
				*(_QWORD*)v28 = *v29;
				*(_QWORD*)(v28 + 8) = v29[1];
			}
			v11 = v74;
		}
		if (v9 >= v10)
			break;
	LABEL_29:
		v6 = v70;
		v13 = (*(_QWORD*)((v9 & state->m_inputMask) + v11) << (64 - (unsigned __int8)v7)) | v19;
	}
	if (v5 != state->m_decompStreamSize)
		goto LABEL_25;
	v30 = state->m_decompSize;
	if (v5 == v30)
	{
		result = 1;
		goto LABEL_69;
	}
	v31 = state->m_inputInvMask;
	v32 = state->m_headerOffset;
	v33 = v31 & -(__int64)v9;
	v19 >>= 1;
	++v7;
	if (v32 > v33)
	{
		v9 += v33;
		v34 = state->qword70;
		if (v9 > v34)
			state->qword70 = v31 + v34 + 1;
	}
	v35 = v9 & state->m_inputMask;
	v9 += v32;
	v36 = v5 + state->m_outputInvMask + 1;
	v37 = *(_QWORD*)(v35 + v11) & ((1i64 << (8 * (unsigned __int8)v32)) - 1);
	v38 = v37 + state->m_bufferSizeNeeded;
	v39 = v37 + state->m_compressedStreamSize;
	state->m_bufferSizeNeeded = v38;
	state->m_compressedStreamSize = v39;
	if (v36 >= v30)
	{
		v36 = v30;
		state->m_compressedStreamSize = v32 + v39;
	}
	state->m_decompStreamSize = v36;
	if (inLen >= v38 && outLen >= v36)
	{
	LABEL_25:
		v10 = state->qword70;
		if (v9 >= v10)
		{
			v9 = ~state->m_inputInvMask & (v9 + 7);
			v10 += state->m_inputInvMask + 1;
			state->qword70 = v10;
		}
		if (state->m_compressedStreamSize < v10)
			v10 = state->m_compressedStreamSize;
		goto LABEL_29;
	}
	v69 = state->qword70;
	if (v9 >= v69)
	{
		v9 = ~v31 & (v9 + 7);
		state->qword70 = v69 + v31 + 1;
	}
	state->dword6C = v71;
	result = 0;
	state->m_currentByte = v19;
	state->m_currentByteBit = v7;
LABEL_69:
	state->m_decompBytePosition = v5;
	state->m_fileBytePosition = v9;
	return result;
}

//----------------------------------------------------------------------------------
// Purpose: start loading shader sets, assign vftable pointer
//----------------------------------------------------------------------------------
void** RTech::LoadShaderSet(void** VTablePtr)
{
	*VTablePtr = &g_pShaderGlueVFTable;
	return &g_pShaderGlueVFTable;
}

//-----------------------------------------------------------------------------
// Purpose: gets information about loaded pak file via pak ID
//-----------------------------------------------------------------------------
PakLoadedInfo_t* RTech::GetPakLoadedInfo(PakHandle_t nHandle)
{
	for (int16_t i = 0; i < *g_pLoadedPakCount; ++i)
	{
		PakLoadedInfo_t* info = &g_pLoadedPakInfo[i];
		if (!info)
			continue;

		if (info->m_handle != nHandle)
			continue;

		return info;
	}

	Warning(eDLL_T::RTECH, "%s - Failed to retrieve pak info for handle '%d'\n", __FUNCTION__, nHandle);
	return nullptr;
}

//-----------------------------------------------------------------------------
// Purpose: gets information about loaded pak file via pak name
//-----------------------------------------------------------------------------
PakLoadedInfo_t* RTech::GetPakLoadedInfo(const char* szPakName)
{
	for (int16_t i = 0; i < *g_pLoadedPakCount; ++i)
	{
		PakLoadedInfo_t* info = &g_pLoadedPakInfo[i];
		if (!info)
			continue;

		if (!info->m_fileName || !*info->m_fileName)
			continue;

		if (strcmp(szPakName, info->m_fileName) != 0)
			continue;

		return info;
	}

	Warning(eDLL_T::RTECH, "%s - Failed to retrieve pak info for name '%s'\n", __FUNCTION__, szPakName);
	return nullptr;
}

//-----------------------------------------------------------------------------
// Purpose: returns pak status as string
//-----------------------------------------------------------------------------
const char* RTech::PakStatusToString(EPakStatus status)
{
	switch (status)
	{
		case EPakStatus::PAK_STATUS_FREED:                  return "PAK_STATUS_FREED";
		case EPakStatus::PAK_STATUS_LOAD_PENDING:           return "PAK_STATUS_LOAD_PENDING";
		case EPakStatus::PAK_STATUS_REPAK_RUNNING:          return "PAK_STATUS_REPAK_RUNNING";
		case EPakStatus::PAK_STATUS_REPAK_DONE:             return "PAK_STATUS_REPAK_DONE";
		case EPakStatus::PAK_STATUS_LOAD_STARTING:          return "PAK_STATUS_LOAD_STARTING";
		case EPakStatus::PAK_STATUS_LOAD_PAKHDR:            return "PAK_STATUS_LOAD_PAKHDR";
		case EPakStatus::PAK_STATUS_LOAD_PATCH_INIT:        return "PAK_STATUS_LOAD_PATCH_INIT";
		case EPakStatus::PAK_STATUS_LOAD_PATCH_EDIT_STREAM: return "PAK_STATUS_LOAD_PATCH_EDIT_STREAM";
		case EPakStatus::PAK_STATUS_LOAD_ASSETS:            return "PAK_STATUS_LOAD_ASSETS";
		case EPakStatus::PAK_STATUS_LOADED:                 return "PAK_STATUS_LOADED";
		case EPakStatus::PAK_STATUS_UNLOAD_PENDING:         return "PAK_STATUS_UNLOAD_PENDING";
		case EPakStatus::PAK_STATUS_FREE_PENDING:           return "PAK_STATUS_FREE_PENDING";
		case EPakStatus::PAK_STATUS_CANCELING:              return "PAK_STATUS_CANCELING";
		case EPakStatus::PAK_STATUS_ERROR:                  return "PAK_STATUS_ERROR";
		case EPakStatus::PAK_STATUS_INVALID_PAKHANDLE:      return "PAK_STATUS_INVALID_PAKHANDLE";
		case EPakStatus::PAK_STATUS_BUSY:                   return "PAK_STATUS_BUSY";
		default:                                              return "PAK_STATUS_UNKNOWN";
	}
}
void V_RTechUtils::Attach() const
{
}

void V_RTechUtils::Detach() const
{
}

///////////////////////////////////////////////////////////////////////////////
RTech* g_pRTech = new RTech();