Merge branch 'Mauler125:pylon' into pylon

This commit is contained in:
Alex 2022-01-15 22:35:16 +02:00 committed by GitHub
commit 194908caca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
137 changed files with 28041 additions and 1174 deletions

View File

@ -3,11 +3,12 @@
#include "tier0/basetypes.h" #include "tier0/basetypes.h"
#include "tier0/IConVar.h" #include "tier0/IConVar.h"
#include "tier0/cvar.h" #include "tier0/cvar.h"
#include "tier0/commandline.h"
#include "client/IVEngineClient.h" #include "client/IVEngineClient.h"
#include "client/client.h" #include "client/client.h"
#include "client/cdll_engine_int.h" #include "client/cdll_engine_int.h"
#include "public/include/bansystem.h"
#include "engine/net_chan.h" #include "engine/net_chan.h"
#include "public/include/bansystem.h"
#include "vpc/keyvalues.h" #include "vpc/keyvalues.h"
/*****************************************************************************/ /*****************************************************************************/
@ -23,23 +24,35 @@ void __fastcall HFrameStageNotify(CHLClient* rcx, ClientFrameStage_t frameStage)
static bool bInitialized = false; static bool bInitialized = false;
if (!bInitialized) if (!bInitialized)
{ {
IConVar_ClearHostNames(); #ifdef GAMEDLL_S3
ConCommand_InitConCommand(); g_pConVar->ClearHostNames();
#endif // GAMEDLL_S3
g_pConCommand->Init();
CKeyValueSystem_Init(); CKeyValueSystem_Init();
if (!g_pCmdLine->CheckParm("-devsdk"))
{
IVEngineClient_CommandExecute(NULL, "exec autoexec.cfg"); IVEngineClient_CommandExecute(NULL, "exec autoexec.cfg");
IVEngineClient_CommandExecute(NULL, "exec autoexec_server.cfg"); IVEngineClient_CommandExecute(NULL, "exec autoexec_server.cfg");
IVEngineClient_CommandExecute(NULL, "exec autoexec_client.cfg"); IVEngineClient_CommandExecute(NULL, "exec autoexec_client.cfg");
}
else // Development configs.
{
IVEngineClient_CommandExecute(NULL, "exec autoexec_dev.cfg");
IVEngineClient_CommandExecute(NULL, "exec autoexec_server_dev.cfg");
IVEngineClient_CommandExecute(NULL, "exec autoexec_client_dev.cfg");
}
*(bool*)m_bRestrictServerCommands = true; // Restrict commands. *(bool*)m_bRestrictServerCommands = true; // Restrict commands.
ConCommandBase* disconnect = (ConCommandBase*)g_pCvar->FindCommand("disconnect"); ConCommandBase* disconnect = (ConCommandBase*)g_pCVar->FindCommand("disconnect");
disconnect->AddFlags(FCVAR_SERVER_CAN_EXECUTE); // Make sure server is not restricted to this. disconnect->AddFlags(FCVAR_SERVER_CAN_EXECUTE); // Make sure server is not restricted to this.
if (net_userandomkey->m_pParent->m_iValue == 1) if (net_userandomkey->GetBool())
{ {
HNET_GenerateKey(); HNET_GenerateKey();
} }
g_pCvar->FindVar("net_usesocketsforloopback")->m_pParent->m_iValue = 1; g_pCVar->FindVar("net_usesocketsforloopback")->SetValue(1);
bInitialized = true; bInitialized = true;
} }

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "tier0/basetypes.h" #include "tier0/basetypes.h"
enum class ClientFrameStage_t : int enum class ClientFrameStage_t : int
{ {
FRAME_UNDEFINED = -1, // (haven't run any frames yet) FRAME_UNDEFINED = -1, // (haven't run any frames yet)
@ -50,6 +49,8 @@ namespace
ADDRESS p_CHLClient_PostInit = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x28\x48\x83\x3D\x00\x00\x00\x00\x00\x48\x8D\x05\x00\x00\x00\x00", "xxxxxxx?????xxx????"); ADDRESS p_CHLClient_PostInit = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x28\x48\x83\x3D\x00\x00\x00\x00\x00\x48\x8D\x05\x00\x00\x00\x00", "xxxxxxx?????xxx????");
void* (*CHLClient_PostInit)() = (void* (*)())p_CHLClient_PostInit.GetPtr(); /*48 83 EC 28 48 83 3D ? ? ? ? ? 48 8D 05 ? ? ? ?*/ void* (*CHLClient_PostInit)() = (void* (*)())p_CHLClient_PostInit.GetPtr(); /*48 83 EC 28 48 83 3D ? ? ? ? ? 48 8D 05 ? ? ? ?*/
#endif #endif
bool* scr_drawloading = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x80\x3D\x00\x00\x00\x00\x00\x74\x14\x66\x0F\x6E\x05\x00\x00\x00\x00", "xx?????xxxxxx????").ResolveRelativeAddress(0x2, 0x7).RCast<bool*>();
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -66,6 +67,7 @@ class HDll_Engine_Int : public IDetour
{ {
std::cout << "| FUN: CHLClient::FrameStageNotify : 0x" << std::hex << std::uppercase << p_CHLClient_FrameStageNotify.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: CHLClient::FrameStageNotify : 0x" << std::hex << std::uppercase << p_CHLClient_FrameStageNotify.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: CHLClient::PostInit : 0x" << std::hex << std::uppercase << p_CHLClient_PostInit.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: CHLClient::PostInit : 0x" << std::hex << std::uppercase << p_CHLClient_PostInit.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| VAR: scr_drawloading : 0x" << std::hex << std::uppercase << scr_drawloading << std::setw(0) << " |" << std::endl;
std::cout << "+----------------------------------------------------------------+" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl;
} }
}; };

View File

@ -6,8 +6,12 @@
#include "tier0/basetypes.h" #include "tier0/basetypes.h"
#include "common/opcodes.h" #include "common/opcodes.h"
#include "engine/host_cmd.h" #include "engine/host_cmd.h"
#include "materialsystem/materialsystem.h"
#include "bsplib/bsplib.h" #include "bsplib/bsplib.h"
#include "ebisusdk/EbisuSDK.h" #include "ebisusdk/EbisuSDK.h"
#ifndef DEDICATED
#include "milessdk/win64_rrthreads.h"
#endif // !DEDICATED
#ifdef DEDICATED #ifdef DEDICATED
@ -126,13 +130,12 @@ void Dedicated_Init()
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// RUNTIME: EBISUSDK // RUNTIME: EBISUSDK
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
p_EbisuSDK_Init_Tier0.Offset(0x0B).Patch({ 0xE9, 0x63, 0x02, 0x00, 0x00, 0x00 }); // JNZ --> JMP | Prevent EbisuSDK from initializing on the engine and server. p_EbisuSDK_SetState.Offset(0x0).FindPatternSelf("0F 84", ADDRESS::Direction::DOWN).Patch({ 0x0F, 0x85 }); // JE --> JNZ | Prevent EbisuSDK from initializing on the engine and server.
p_EbisuSDK_SetState.Offset(0x0E).Patch({ 0xE9, 0xCB, 0x03, 0x00, 0x00 }); // JNZ --> JMP | Prevent EbisuSDK from initializing on the engine and server.
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// RUNTIME: FAIRFIGHT // RUNTIME: FAIRFIGHT
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
FairFight_Init.Offset(0x61).Patch({ 0xE9, 0xED, 0x00, 0x00, 0x00, 0x00 }); FairFight_Init.Offset(0x0).FindPatternSelf("0F 87", ADDRESS::Direction::DOWN, 200).Patch({ 0x0F, 0x85 }); // JA --> JNZ | Prevent 'FairFight' anti-cheat from initializing on the server by comparing RAX against 0x0 instead. Init will crash since the plugins aren't shipped.
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// RUNTIME: BSP_LUMP // RUNTIME: BSP_LUMP
@ -170,18 +173,16 @@ void Dedicated_Init()
void RuntimePtc_Init() /* .TEXT */ void RuntimePtc_Init() /* .TEXT */
{ {
SCR_BeginLoadingPlaque.Offset(0x1D6).Patch({ 0xEB, 0x27 }); // JNE --> JMP | Prevent connect command from crashing by invalid call to UI function. #ifndef DEDICATED
//------------------------------------------------------------------------- p_WASAPI_GetAudioDevice.Offset(0x410).FindPattern("FF 15 ?? ?? 01 00", ADDRESS::Direction::DOWN, 100).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xEB }); // CAL --> NOP | Disable debugger check when miles searches for audio device to allow attaching the debugger to the game upon launch.
// JNE --> JMP | Allow games to be loaded without the optional texture streaming file FairFight_Init.Offset(0x0).FindPatternSelf("0F 87", ADDRESS::Direction::DOWN, 200).Patch({ 0x0F, 0x85 }); // JA --> JNZ | Prevent 'FairFight' anti-cheat from initializing on the server by comparing RAX against 0x0 instead. Init will crash since the plugins aren't shipped.
//WriteProcessMemory(GameProcess, LPVOID(dst002 + 0x8E5), "\xEB\x19", 2, NULL); SCR_BeginLoadingPlaque.Offset(0x1AD).FindPatternSelf("75 27", ADDRESS::Direction::DOWN).Patch({ 0xEB, 0x27 }); // JNE --> JMP | Prevent connect command from crashing by invalid call to UI function.
//------------------------------------------------------------------------- #endif // !DEDICATED
//-------------------------------------------------------------------------
// JA --> JMP | Prevent FairFight anti-cheat from initializing on the server.
FairFight_Init.Offset(0x61).Patch({ 0xE9, 0xED, 0x00, 0x00, 0x00, 0x00 });
} }
void RuntimePtc_Toggle() /* .TEXT */ void RuntimePtc_Toggle() /* .TEXT */
{ {
#ifdef GAMEDLL_S3
static bool g_nop = true; static bool g_nop = true;
if (g_nop) if (g_nop)
@ -191,7 +192,7 @@ void RuntimePtc_Toggle() /* .TEXT */
dst007.Offset(0x5E8).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }); dst007.Offset(0x5E8).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 });
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// CALL --> NOP | Disable the viewmodel rendered to avoid a crash from a certain entity in desertlands_mu1 // CALL --> NOP | Disable the viewmodel rendered to avoid a crash from a certain entity in desertlands_mu1
dst008.Offset(0x67).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90 }); //dst008.Offset(0x67).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90 });
printf("\n"); printf("\n");
@ -207,7 +208,7 @@ void RuntimePtc_Toggle() /* .TEXT */
dst007.Offset(0x5E8).Patch({ 0x48, 0x8B, 0x03, 0xFF, 0x90, 0xB0, 0x02, 0x00, 0x00, 0x84, 0xC0 }); dst007.Offset(0x5E8).Patch({ 0x48, 0x8B, 0x03, 0xFF, 0x90, 0xB0, 0x02, 0x00, 0x00, 0x84, 0xC0 });
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// NOP --> CALL | Recover function DST008 // NOP --> CALL | Recover function DST008
dst008.Offset(0x67).Patch({ 0xE8, 0x54, 0xD8, 0xFF, 0xFF }); //dst008.Offset(0x67).Patch({ 0xE8, 0x54, 0xD8, 0xFF, 0xFF });
printf("\n"); printf("\n");
printf("+--------------------------------------------------------+\n"); printf("+--------------------------------------------------------+\n");
@ -216,4 +217,13 @@ void RuntimePtc_Toggle() /* .TEXT */
printf("\n"); printf("\n");
} }
g_nop = !g_nop; g_nop = !g_nop;
/*
rtech_asyncload "common.rpak"
rtech_asyncload "common_mp.rpak"
rtech_asyncload "mp_rr_canyonlands_mu1.rpak"
rtech_asyncload "mp_rr_desertlands_64k_x_64k.rpak"
*/
#endif // GAMEDLL_S3
} }

View File

@ -1,4 +1,6 @@
#pragma once #pragma once
#include "tier0/basetypes.h"
namespace namespace
{ {
#ifdef DEDICATED #ifdef DEDICATED
@ -14,11 +16,12 @@ void RuntimePtc_Toggle();
namespace namespace
{ {
#ifdef GAMEDLL_S3
/* -------------- OTHER ------------------------------------------------------------------------------------------------------------------------------------------------- */ /* -------------- OTHER ------------------------------------------------------------------------------------------------------------------------------------------------- */
ADDRESS dst007 = /*0x14028F3B0*/ FindPatternSIMD(g_szGameDll, (const unsigned char*)"\x48\x8B\xC4\x44\x89\x40\x18\x48\x89\x50\x10\x55\x53\x56\x57\x41", "xxxxxxxxxxxxxxxx"); ADDRESS dst007 = /*0x14028F3B0*/ FindPatternSIMD(g_szGameDll, (const unsigned char*)"\x48\x8B\xC4\x44\x89\x40\x18\x48\x89\x50\x10\x55\x53\x56\x57\x41", "xxxxxxxxxxxxxxxx");
ADDRESS dst008 = /*0x140E3E110*/ FindPatternSIMD(g_szGameDll, (const unsigned char*)"\x48\x83\xEC\x78\x48\x8B\x84\x24\x00\x00\x00\x00\x4D\x8B\xD8\x00", "xxxxxxxx????xxx?"); ADDRESS dst008 = /*0x140E3E110*/ FindPatternSIMD(g_szGameDll, (const unsigned char*)"\x48\x83\xEC\x78\x48\x8B\x84\x24\x00\x00\x00\x00\x4D\x8B\xD8\x00", "xxxxxxxx????xxx?");
/* -------------- ------- ----------------------------------------------------------------------------------------------------------------------------------------------- */ /* -------------- ------- ----------------------------------------------------------------------------------------------------------------------------------------------- */
#endif // GAMEDLL_S3
namespace namespace
{ {
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -57,15 +60,6 @@ namespace
ADDRESS CShaderSystem__Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x20\xC6\x41\x10\x00", "xxxx?xxxx?xxxxxxxxx"); ADDRESS CShaderSystem__Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x20\xC6\x41\x10\x00", "xxxx?xxxx?xxxxxxxxx");
// 0x1403DF870 // 48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 C6 41 10 00 // // 0x1403DF870 // 48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 C6 41 10 00 //
//-------------------------------------------------------------------------
// CMATERIALSYSTEM
//-------------------------------------------------------------------------
ADDRESS CMaterialSystem__Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x70\x48\x83\x3D\x00\x00\x00\x00\x00", "xxxx?xxxxxxxxxxxxxxxxxx?????");
// 0x1403BBFD0 // 48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 70 48 83 3D ? ? ? ? ? //
ADDRESS InitMaterialSystem = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x28\x48\x8B\x0D\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x48\x8B\x01\xFF\x90\x00\x00\x00\x00\x48\x8B\x0D\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x48\x8B\x01\xFF\x90\x00\x00\x00\x00", "xxxxxxx????xxx????xxxxx????xxx????xxx????xxxxx????"); //
// 0x14024B390 // 48 83 EC 28 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? 48 8B 01 FF 90 ? ? ? ? 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? 48 8B 01 FF 90 ? ? ? ? //
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// RUNTIME: BSP_LUMP // RUNTIME: BSP_LUMP
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -75,19 +69,37 @@ namespace
ADDRESS CollisionBSPData_LinkPhysics = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x57\x48\x81\xEC\x00\x00\x00\x00\x48\x8B\xF9\x33\xED", "xxxx?xxxx?xxxx????xxxxx"); // case 1: only gets called on changelevel, needs more research, function gets called by CModelLoader virtual function. ADDRESS CollisionBSPData_LinkPhysics = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x57\x48\x81\xEC\x00\x00\x00\x00\x48\x8B\xF9\x33\xED", "xxxx?xxxx?xxxx????xxxxx"); // case 1: only gets called on changelevel, needs more research, function gets called by CModelLoader virtual function.
// 0x140256480 // 48 89 5C 24 ? 48 89 6C 24 ? 57 48 81 EC ? ? ? ? 48 8B F9 33 ED // // 0x140256480 // 48 89 5C 24 ? 48 89 6C 24 ? 57 48 81 EC ? ? ? ? 48 8B F9 33 ED //
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// CSTUDIORENDERCONTEXT // CSTUDIORENDERCONTEXT
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
#if defined (GAMEDLL_S1)
ADDRESS CStudioRenderContext__LoadModel = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x4C\x89\x44\x24\x00\x53\x55\x56\x41\x54\x41\x57", "xxxx?xxxxxxx");
#elif defined (GAMEDLL_S2)
ADDRESS CStudioRenderContext__LoadModel = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x4C\x89\x44\x24\x00\x48\x89\x54\x24\x00\x53\x57\x41\x55\x48\x81\xEC\x00\x00\x00\x00", "xxxx?xxxx?xxxxxxx????");
#elif defined (GAMEDLL_S3)
ADDRESS CStudioRenderContext__LoadModel = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x4C\x89\x44\x24\x00\x48\x89\x54\x24\x00\x48\x89\x4C\x24\x00\x53\x55\x56\x57\x48\x83\xEC\x78", "xxxx?xxxx?xxxx?xxxxxxxx"); ADDRESS CStudioRenderContext__LoadModel = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x4C\x89\x44\x24\x00\x48\x89\x54\x24\x00\x48\x89\x4C\x24\x00\x53\x55\x56\x57\x48\x83\xEC\x78", "xxxx?xxxx?xxxx?xxxxxxxx");
// 0x1404554C0 // 4C 89 44 24 ? 48 89 54 24 ? 48 89 4C 24 ? 53 55 56 57 48 83 EC 78 // #endif// 0x1404554C0 // 4C 89 44 24 ? 48 89 54 24 ? 48 89 4C 24 ? 53 55 56 57 48 83 EC 78 //
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
ADDRESS CStudioRenderContext__LoadMaterials = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x4C\x89\x44\x24\x00\x55\x56\x41\x57", "xxxx?xxxx");
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
ADDRESS CStudioRenderContext__LoadMaterials = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x8B\xC4\x4C\x89\x40\x18\x55\x56\x41\x55", "xxxxxxxxxxx"); ADDRESS CStudioRenderContext__LoadMaterials = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x8B\xC4\x4C\x89\x40\x18\x55\x56\x41\x55", "xxxxxxxxxxx");
// 0x140456B50 // 48 8B C4 4C 89 40 18 55 56 41 55 // #endif// 0x140456B50 // 48 8B C4 4C 89 40 18 55 56 41 55 //
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// CMODELLOADER // CMODELLOADER
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
ADDRESS CModelLoader__FindModel = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x55\x41\x55\x41\x56\x48\x8D\xAC\x24\x00\x00\x00\x00", "xxxxxxxxxx????");
// 0x1402A1F10 // 40 55 41 55 41 56 48 8D AC 24 ? ? ? ? //
ADDRESS CModelLoader__LoadModel = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x57\x41\x56\x48\x81\xEC\x00\x00\x00\x00\x48\x8B\xFA", "xxxxxxxx????xxx");
// 0x1402A23B0 // 40 53 57 41 56 48 81 EC ? ? ? ? 48 8B FA //
ADDRESS CModelLoader__Studio_LoadModel = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x55\x56\x57\x41\x54\x41\x56\x48\x8D\xAC\x24\x00\x00\x00\x00", "xxxx?xxxxxxxxxxx????");
// 0x140252F10 // 48 89 5C 24 ? 55 56 57 41 54 41 57 48 81 EC ? ? ? ? //
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
ADDRESS CModelLoader__FindModel = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x55\x41\x57\x48\x83\xEC\x48\x80\x3A\x2A", "xxxxxxxxxxx"); ADDRESS CModelLoader__FindModel = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x55\x41\x57\x48\x83\xEC\x48\x80\x3A\x2A", "xxxxxxxxxxx");
// 0x140253530 // 40 55 41 57 48 83 EC 48 80 3A 2A // // 0x140253530 // 40 55 41 57 48 83 EC 48 80 3A 2A //
@ -96,18 +108,26 @@ namespace
ADDRESS CModelLoader__Studio_LoadModel = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x55\x56\x57\x41\x54\x41\x57\x48\x81\xEC\x00\x00\x00\x00", "xxxx?xxxxxxxxxx????"); ADDRESS CModelLoader__Studio_LoadModel = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x55\x56\x57\x41\x54\x41\x57\x48\x81\xEC\x00\x00\x00\x00", "xxxx?xxxxxxxxxx????");
// 0x140252F10 // 48 89 5C 24 ? 55 56 57 41 54 41 57 48 81 EC ? ? ? ? // // 0x140252F10 // 48 89 5C 24 ? 55 56 57 41 54 41 57 48 81 EC ? ? ? ? //
#endif
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// CGAMESERVER // CGAMESERVER
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
ADDRESS CGameServer__SpawnServer = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x55\x56\x57\x41\x55\x41\x56\x41\x57\x48\x81\xEC\x00\x00\x00\x00", "xxxxxxxxxxxxxx????");
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
ADDRESS CGameServer__SpawnServer = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x8B\xC4\x53\x55\x56\x57\x41\x54\x41\x55\x41\x57", "xxxxxxxxxxxxx"); ADDRESS CGameServer__SpawnServer = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x8B\xC4\x53\x55\x56\x57\x41\x54\x41\x55\x41\x57", "xxxxxxxxxxxxx");
// 0x140312D80 // 48 8B C4 53 55 56 57 41 54 41 55 41 57 // // 0x140312D80 // 48 8B C4 53 55 56 57 41 54 41 55 41 57 //
#endif
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// RUNTIME: FAIRFIGHT // RUNTIME: FAIRFIGHT
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
ADDRESS FairFight_Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x57\x41\x57\x48\x83\xEC\x30\x8B\x81\x00\x00\x00\x00", "xxxxxxxxxxx????");
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
ADDRESS FairFight_Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x8B\x81\xB0\x03\x00\x00\x48\x8B\xD9\xC6", "xxxxxxxxxxxxxxxx"); ADDRESS FairFight_Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x8B\x81\xB0\x03\x00\x00\x48\x8B\xD9\xC6", "xxxxxxxxxxxxxxxx");
// 0x140303AE0 // 40 53 48 83 EC 20 8B 81 ? ? ? ? 48 8B D9 C6 81 ? ? ? ? ? // #endif // 0x140303AE0 // 40 53 48 83 EC 20 8B 81 ? ? ? ? 48 8B D9 C6 81 ? ? ? ? ? //
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// RUNTIME: HOST_INIT // RUNTIME: HOST_INIT
@ -136,8 +156,14 @@ namespace
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// RUNTIME: GL_SCREEN // RUNTIME: GL_SCREEN
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
ADDRESS SCR_BeginLoadingPlaque = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x83\xEC\x30\x0F\x29\x74\x24\x00\x48\x8B\xF9", "xxxx?xxxx?xxxxxxxxx?xxx");
// 0x14022A4A0 // 48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 30 0F 29 74 24 ? 48 8B F9 //
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
ADDRESS SCR_BeginLoadingPlaque = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x38\x0F\x29\x74\x24\x00\x48\x89\x5C\x24\x00", "xxxxxxxx?xxxx?"); ADDRESS SCR_BeginLoadingPlaque = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x38\x0F\x29\x74\x24\x00\x48\x89\x5C\x24\x00", "xxxxxxxx?xxxx?");
// 0x14022A4A0 // 48 83 EC 38 0F 29 74 24 ? 48 89 5C 24 ? // // 0x14022A4A0 // 48 83 EC 38 0F 29 74 24 ? 48 89 5C 24 ? //
#endif
} }
} }
@ -153,9 +179,6 @@ class HOpcodes : public IDetour
std::cout << "+----------------------------------------------------------------+" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl;
std::cout << "| FUN: CShaderSystem::Init : 0x" << std::hex << std::uppercase << CShaderSystem__Init.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: CShaderSystem::Init : 0x" << std::hex << std::uppercase << CShaderSystem__Init.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "+----------------------------------------------------------------+" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl;
std::cout << "| FUN: CMaterialSystem::Init : 0x" << std::hex << std::uppercase << CMaterialSystem__Init.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: InitMaterialSystem : 0x" << std::hex << std::uppercase << InitMaterialSystem.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "+----------------------------------------------------------------+" << std::endl;
std::cout << "| FUN: CollisionBSPData_LoadAllLumps : 0x" << std::hex << std::uppercase << CollisionBSPData_LoadAllLumps.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: CollisionBSPData_LoadAllLumps : 0x" << std::hex << std::uppercase << CollisionBSPData_LoadAllLumps.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: CollisionBSPData_LinkPhysics : 0x" << std::hex << std::uppercase << CollisionBSPData_LinkPhysics.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: CollisionBSPData_LinkPhysics : 0x" << std::hex << std::uppercase << CollisionBSPData_LinkPhysics.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "+----------------------------------------------------------------+" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl;

13
r5dev/core/assert.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#ifndef NDEBUG
# define Assert(condition, message) \
do { \
if (! (condition)) { \
std::cerr << "Assertion `" #condition "` failed in " << __FILE__ \
<< " line " << __LINE__ << ": " << message << std::endl; \
std::terminate(); \
} \
} while (false)
#else
# define Assert(condition, message) do { } while (false)
#endif

View File

@ -1,6 +1,7 @@
#include "core/stdafx.h" #include "core/stdafx.h"
#include "core/r5dev.h" #include "core/r5dev.h"
#include "core/init.h" #include "core/init.h"
#include "core/logdef.h"
/*****************************************************************************/ /*****************************************************************************/
#ifndef DEDICATED #ifndef DEDICATED
#include "windows/id3dx.h" #include "windows/id3dx.h"
@ -15,7 +16,13 @@
void R5Dev_Init() void R5Dev_Init()
{ {
#ifndef DEDICATED
if (strstr(GetCommandLineA(), "-wconsole")) { Console_Init(); }
#else
Console_Init(); Console_Init();
#endif // !DEDICATED
SpdLog_Init();
Systems_Init(); Systems_Init();
WinSys_Attach(); WinSys_Attach();
@ -24,13 +31,17 @@ void R5Dev_Init()
DirectX_Init(); DirectX_Init();
#endif // !DEDICATED #endif // !DEDICATED
spdlog::get("console")->set_pattern("%v"); spdlog::info("\n");
spdlog::info("+-----------------------------------------------------------------------------+\n"); spdlog::info("+-----------------------------------------------------------------------------+\n");
spdlog::info("| R5 DEVELOPER CONSOLE -- INITIALIZED ----------------------------------- |\n"); spdlog::info("| R5 DEVELOPER CONSOLE -- INITIALIZED ----------------------------------- |\n");
spdlog::info("+-----------------------------------------------------------------------------+\n"); spdlog::info("+-----------------------------------------------------------------------------+\n");
spdlog::get("console")->set_pattern("[%S.%e] %v"); spdlog::info("\n");
} }
//#############################################################################
// SHUTDOWN
//#############################################################################
void R5Dev_Shutdown() void R5Dev_Shutdown()
{ {
Systems_Shutdown(); Systems_Shutdown();

View File

@ -6,7 +6,7 @@
#include "core/stdafx.h" #include "core/stdafx.h"
#include "core/init.h" #include "core/init.h"
#include "common/opcodes.h" #include "tier0/commandline.h"
#include "tier0/ConCommand.h" #include "tier0/ConCommand.h"
#include "tier0/completion.h" #include "tier0/completion.h"
#include "tier0/cvar.h" #include "tier0/cvar.h"
@ -15,11 +15,16 @@
#include "vpc/keyvalues.h" #include "vpc/keyvalues.h"
#include "vpc/basefilesystem.h" #include "vpc/basefilesystem.h"
#include "vpc/keyvalues.h" #include "vpc/keyvalues.h"
#include "common/opcodes.h"
#include "launcher/IApplication.h" #include "launcher/IApplication.h"
#include "ebisusdk/EbisuSDK.h" #include "ebisusdk/EbisuSDK.h"
#ifndef DEDICATED
#include "milessdk/win64_rrthreads.h"
#endif // !DEDICATED
#include "vphysics/QHull.h" #include "vphysics/QHull.h"
#include "bsplib/bsplib.h" #include "bsplib/bsplib.h"
#ifndef DEDICATED #ifndef DEDICATED
#include "materialsystem/materialsystem.h"
#include "vgui/CEngineVGui.h" #include "vgui/CEngineVGui.h"
#include "vgui/vgui_fpspanel.h" #include "vgui/vgui_fpspanel.h"
#include "vguimatsurface/MatSystemSurface.h" #include "vguimatsurface/MatSystemSurface.h"
@ -42,6 +47,7 @@
#include "engine/sys_dll2.h" #include "engine/sys_dll2.h"
#include "engine/sys_utils.h" #include "engine/sys_utils.h"
#ifndef DEDICATED #ifndef DEDICATED
#include "engine/debugoverlay.h"
#include "inputsystem/inputsystem.h" #include "inputsystem/inputsystem.h"
#include "windows/id3dx.h" #include "windows/id3dx.h"
#endif // !DEDICATED #endif // !DEDICATED
@ -78,7 +84,9 @@ void Systems_Init()
CHLClient_Attach(); CHLClient_Attach();
#endif // !DEDICATED #endif // !DEDICATED
CServer_Attach(); #ifdef GAMEDLL_S3
CServer_Attach(); // S1 and S2 CServer functions require work.
#endif // GAMEDLL_S3
#ifdef DEDICATED #ifdef DEDICATED
CHostState_Attach(); // Dedicated only for now until backwards compatible with S1. CHostState_Attach(); // Dedicated only for now until backwards compatible with S1.
@ -107,12 +115,11 @@ void Systems_Init()
TerminateProcess(GetCurrentProcess(), 0xBAD0C0DE); TerminateProcess(GetCurrentProcess(), 0xBAD0C0DE);
} }
IConVar_InitConVar(); g_pConVar->Init();
#ifdef DEDICATED #ifdef DEDICATED
Dedicated_Init(); Dedicated_Init();
#endif // DEDICATED #endif // DEDICATED
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -145,7 +152,10 @@ void Systems_Shutdown()
CFPSPanel_Detach(); CFPSPanel_Detach();
CHLClient_Detach(); CHLClient_Detach();
#endif // !DEDICATED #endif // !DEDICATED
CServer_Detach();
#ifdef GAMEDLL_S3
CServer_Detach(); // S1 and S2 CServer functions require work.
#endif // GAMEDLL_S3
#ifdef DEDICATED #ifdef DEDICATED
CHostState_Detach(); // Dedicated only for now until backwards compatible with S1. CHostState_Detach(); // Dedicated only for now until backwards compatible with S1.

60
r5dev/core/logdef.cpp Normal file
View File

@ -0,0 +1,60 @@
#include "core/stdafx.h"
#include "core/logdef.h"
//#############################################################################
// SPDLOG SETUP
//#############################################################################
void SpdLog_Init(void)
{
static bool bInitialized = false;
if (bInitialized)
{
Assert(bInitialized, "'SpdLog_Init()' has already been called.");
return;
}
/************************
* IMGUI LOGGER SETUP *
************************/
{
auto iconsole = std::make_shared<spdlog::logger>("game_console", g_spd_sys_p_ostream_sink);
spdlog::register_logger(iconsole); // in-game console logger.
iconsole->set_pattern("[%S.%e] %v");
iconsole->set_level(spdlog::level::trace);
}
/************************
* WINDOWS LOGGER SETUP *
************************/
{
auto wconsole = spdlog::stdout_logger_mt("win_console");
// Determine if user wants ansi-color logging in the terminal.
if (strstr(GetCommandLineA(), "-ansiclr"))
{
wconsole->set_pattern("[%S.%e] %v\u001b[0m");
g_bSpdLog_UseAnsiClr = true;
}
else { wconsole->set_pattern("[%S.%e] %v"); }
wconsole->set_level(spdlog::level::trace);
spdlog::set_default_logger(wconsole); // Set as default.
}
/************************
* ROTATE LOGGER SETUP *
************************/
{
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("sqvm_warn_logger", "platform\\logs\\sqvm_warn.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("sqvm_print_logger", "platform\\logs\\sqvm_print.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("dev_message_logger", "platform\\logs\\dev_message.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("netchan_pack_logger", "platform\\logs\\net_trace.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("qhull_debug_logger", "platform\\logs\\qhull_print.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
spdlog::rotating_logger_mt<spdlog::synchronous_factory>("filesystem_warn_logger", "platform\\logs\\fs_warn.log", SPDLOG_MAX_SIZE, SPDLOG_NUM_FILE)->set_pattern("[%Y-%m-%d %H:%M:%S.%e] %v");
}
spdlog::set_level(spdlog::level::trace);
spdlog::flush_every(std::chrono::seconds(5)); // Flush buffers every 5 seconds for every logger.
bInitialized = true;
}

View File

@ -1,27 +1,13 @@
#pragma once #pragma once
constexpr int SPDLOG_MAX_SIZE = 10 * 1024; // Sets number of bytes before rotating logger.
constexpr int SPDLOG_NUM_FILE = 0; // Sets number of files to rotate to.
inline bool g_bSpdLog_UseAnsiClr = false;
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// NETCHAN | // IMGUI CONSOLE SINK |
inline auto g_spd_netchan_logger = spdlog::basic_logger_mt("netchan_logger", "platform\\logs\\net_trace.log");
inline std::ostringstream g_spd_net_p_oss;
inline auto g_spd_net_p_ostream_sink = std::make_shared<spdlog::sinks::ostream_sink_st>(g_spd_net_p_oss);
//-------------------------------------------------------------------------
// FILESYSTEM |
inline std::ostringstream fs_oss;
inline auto fs_ostream_sink = std::make_shared<spdlog::sinks::ostream_sink_st>(fs_oss);
//-------------------------------------------------------------------------
// SQUIRREL PRINTF |
inline std::ostringstream g_spd_sqvm_p_oss;
inline auto g_spd_sqvm_p_ostream_sink = std::make_shared<spdlog::sinks::ostream_sink_st>(g_spd_sqvm_p_oss);
//-------------------------------------------------------------------------
// SQUIRREL WARNF |
inline std::ostringstream g_spd_sqvm_w_oss;
inline auto g_spd_sqvm_w_ostream_sink = std::make_shared<spdlog::sinks::ostream_sink_st>(g_spd_sqvm_w_oss);
//-------------------------------------------------------------------------
// SYSTEM PRINTF |
inline std::ostringstream g_spd_sys_w_oss; inline std::ostringstream g_spd_sys_w_oss;
inline auto g_spd_sys_p_ostream_sink = std::make_shared<spdlog::sinks::ostream_sink_st>(g_spd_sys_w_oss); inline auto g_spd_sys_p_ostream_sink = std::make_shared<spdlog::sinks::ostream_sink_st>(g_spd_sys_w_oss);
//-------------------------------------------------------------------------
// QHULL PRINTF | void SpdLog_Init(void);
inline std::ostringstream g_spd_qhull_p_w_oss;
inline auto g_spd_qhull_p_ostream_sink = std::make_shared<spdlog::sinks::ostream_sink_st>(g_spd_qhull_p_w_oss);

View File

@ -36,27 +36,38 @@
#include "thirdparty/imgui/include/imgui_impl_win32.h" #include "thirdparty/imgui/include/imgui_impl_win32.h"
#endif // !DEDICATED #endif // !DEDICATED
#if !defined(SDKLAUNCHER)
#include "thirdparty/lzham/include/lzham_types.h"
#include "thirdparty/lzham/include/lzham.h"
#endif // !SDKLAUNCHER
#include "thirdparty/spdlog/include/spdlog.h" #include "thirdparty/spdlog/include/spdlog.h"
#include "thirdparty/spdlog/include/async.h"
#include "thirdparty/spdlog/include/sinks/ostream_sink.h"
#include "thirdparty/spdlog/include/sinks/basic_file_sink.h" #include "thirdparty/spdlog/include/sinks/basic_file_sink.h"
#include "thirdparty/spdlog/include/sinks/stdout_sinks.h" #include "thirdparty/spdlog/include/sinks/stdout_sinks.h"
#include "thirdparty/spdlog/include/sinks/ostream_sink.h" #include "thirdparty/spdlog/include/sinks/stdout_color_sinks.h"
#include "thirdparty/spdlog/include/sinks/ansicolor_sink.h"
#include "thirdparty/spdlog/include/sinks/rotating_file_sink.h"
#include "public/include/utility.h" #include "public/include/utility.h"
#include "public/include/memaddr.h" #include "public/include/memaddr.h"
#include "public/include/httplib.h" #include "public/include/httplib.h"
#include "public/include/json.hpp" #include "public/include/json.hpp"
#include "networksystem/net_structs.h" #include "tier0/basetypes.h"
#include "core/assert.h"
#ifndef SDKLAUNCHER #if !defined (SDKLAUNCHER)
namespace namespace
{ {
#ifdef DEDICATED #if !defined (DEDICATED)
MODULE g_mGameDll = MODULE("r5apex_ds.exe");
#else
MODULE g_mGameDll = MODULE("r5apex.exe"); MODULE g_mGameDll = MODULE("r5apex.exe");
#endif // DEDICATED #else
MODULE g_mGameDll = MODULE("r5apex_ds.exe");
#endif // !DEDICATED
MODULE g_mRadVideoToolsDll = MODULE("bink2w64.dll"); MODULE g_mRadVideoToolsDll = MODULE("bink2w64.dll");
MODULE g_mRadAudioDecoderDll = MODULE("binkawin64.dll"); MODULE g_mRadAudioDecoderDll = MODULE("binkawin64.dll");
MODULE g_mRadAudioSystemDll = MODULE("mileswin64.dll"); MODULE g_mRadAudioSystemDll = MODULE("mileswin64.dll");
} }
#endif // SDKLAUNCHER #endif // !SDKLAUNCHER

View File

@ -135,7 +135,7 @@
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>detours.lib;lzhamlib_x64D.lib;lzhamcomp_x64D.lib;lzhamdecomp_x64D.lib;d3d11.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>User32.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<PostBuildEvent> <PostBuildEvent>
<Command>del "..\..\..\$(ProjectName)" &amp;&amp; copy /Y "$(TargetPath)" "..\..\..\</Command> <Command>del "..\..\..\$(ProjectName)" &amp;&amp; copy /Y "$(TargetPath)" "..\..\..\</Command>
@ -162,7 +162,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>detours.lib;lzhamlib_x64.lib;lzhamcomp_x64.lib;lzhamdecomp_x64.lib;d3d11.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>User32.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<PostBuildEvent> <PostBuildEvent>
<Command>del "..\..\..\$(ProjectName)" &amp;&amp; copy /Y "$(TargetPath)" "..\..\..\</Command> <Command>del "..\..\..\$(ProjectName)" &amp;&amp; copy /Y "$(TargetPath)" "..\..\..\</Command>
@ -175,13 +175,13 @@
<ClInclude Include="common\opcodes.h" /> <ClInclude Include="common\opcodes.h" />
<ClInclude Include="common\protocol.h" /> <ClInclude Include="common\protocol.h" />
<ClInclude Include="common\psuedodefs.h" /> <ClInclude Include="common\psuedodefs.h" />
<ClInclude Include="core\assert.h" />
<ClInclude Include="core\init.h" /> <ClInclude Include="core\init.h" />
<ClInclude Include="core\logdef.h" /> <ClInclude Include="core\logdef.h" />
<ClInclude Include="core\r5dev.h" /> <ClInclude Include="core\r5dev.h" />
<ClInclude Include="core\stdafx.h" /> <ClInclude Include="core\stdafx.h" />
<ClInclude Include="ebisusdk\EbisuSDK.h" /> <ClInclude Include="ebisusdk\EbisuSDK.h" />
<ClInclude Include="engine\baseclient.h" /> <ClInclude Include="engine\baseclient.h" />
<ClInclude Include="engine\baseclientstate.h" />
<ClInclude Include="engine\host_cmd.h" /> <ClInclude Include="engine\host_cmd.h" />
<ClInclude Include="engine\host_state.h" /> <ClInclude Include="engine\host_state.h" />
<ClInclude Include="engine\net_chan.h" /> <ClInclude Include="engine\net_chan.h" />
@ -190,6 +190,7 @@
<ClInclude Include="engine\sys_utils.h" /> <ClInclude Include="engine\sys_utils.h" />
<ClInclude Include="launcher\IApplication.h" /> <ClInclude Include="launcher\IApplication.h" />
<ClInclude Include="mathlib\adler32.h" /> <ClInclude Include="mathlib\adler32.h" />
<ClInclude Include="mathlib\bits.h" />
<ClInclude Include="mathlib\crc32.h" /> <ClInclude Include="mathlib\crc32.h" />
<ClInclude Include="mathlib\IceKey.H" /> <ClInclude Include="mathlib\IceKey.H" />
<ClInclude Include="mathlib\parallel_for.h" /> <ClInclude Include="mathlib\parallel_for.h" />
@ -216,7 +217,34 @@
<ClInclude Include="thirdparty\detours\include\idetour.h" /> <ClInclude Include="thirdparty\detours\include\idetour.h" />
<ClInclude Include="thirdparty\detours\include\syelog.h" /> <ClInclude Include="thirdparty\detours\include\syelog.h" />
<ClInclude Include="thirdparty\lzham\include\lzham.h" /> <ClInclude Include="thirdparty\lzham\include\lzham.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_assert.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_checksum.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_config.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_core.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_helpers.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_huffman_codes.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_lzbase.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_match_accel.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_math.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_mem.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_null_threading.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_platform.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_polar_codes.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_prefix_coding.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_pthreads_threading.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_static_lib.h" /> <ClInclude Include="thirdparty\lzham\include\lzham_static_lib.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_symbol_codec.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_threading.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_timer.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_traits.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_types.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_utils.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_vector.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_win32_threading.h" />
<ClInclude Include="thirdparty\lzham\lzhamcomp\lzham_comp.h" />
<ClInclude Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp_internal.h" />
<ClInclude Include="thirdparty\lzham\lzhamdecomp\lzham_decomp.h" />
<ClInclude Include="thirdparty\lzham\lzhamdecomp\lzham_lzdecompbase.h" />
<ClInclude Include="thirdparty\spdlog\include\async.h" /> <ClInclude Include="thirdparty\spdlog\include\async.h" />
<ClInclude Include="thirdparty\spdlog\include\async_logger-inl.h" /> <ClInclude Include="thirdparty\spdlog\include\async_logger-inl.h" />
<ClInclude Include="thirdparty\spdlog\include\async_logger.h" /> <ClInclude Include="thirdparty\spdlog\include\async_logger.h" />
@ -312,6 +340,7 @@
<ClInclude Include="thirdparty\spdlog\include\tweakme.h" /> <ClInclude Include="thirdparty\spdlog\include\tweakme.h" />
<ClInclude Include="thirdparty\spdlog\include\version.h" /> <ClInclude Include="thirdparty\spdlog\include\version.h" />
<ClInclude Include="tier0\basetypes.h" /> <ClInclude Include="tier0\basetypes.h" />
<ClInclude Include="tier0\commandline.h" />
<ClInclude Include="tier0\ConCommand.h" /> <ClInclude Include="tier0\ConCommand.h" />
<ClInclude Include="tier0\completion.h" /> <ClInclude Include="tier0\completion.h" />
<ClInclude Include="tier0\cvar.h" /> <ClInclude Include="tier0\cvar.h" />
@ -333,13 +362,13 @@
<ClCompile Include="common\opcodes.cpp" /> <ClCompile Include="common\opcodes.cpp" />
<ClCompile Include="core\dllmain.cpp" /> <ClCompile Include="core\dllmain.cpp" />
<ClCompile Include="core\init.cpp" /> <ClCompile Include="core\init.cpp" />
<ClCompile Include="core\logdef.cpp" />
<ClCompile Include="core\stdafx.cpp"> <ClCompile Include="core\stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="ebisusdk\EbisuSDK.cpp" /> <ClCompile Include="ebisusdk\EbisuSDK.cpp" />
<ClCompile Include="engine\baseclient.cpp" /> <ClCompile Include="engine\baseclient.cpp" />
<ClCompile Include="engine\baseclientstate.cpp" />
<ClCompile Include="engine\host_cmd.cpp" /> <ClCompile Include="engine\host_cmd.cpp" />
<ClCompile Include="engine\host_state.cpp" /> <ClCompile Include="engine\host_state.cpp" />
<ClCompile Include="engine\net_chan.cpp" /> <ClCompile Include="engine\net_chan.cpp" />
@ -348,6 +377,7 @@
<ClCompile Include="engine\sys_utils.cpp" /> <ClCompile Include="engine\sys_utils.cpp" />
<ClCompile Include="launcher\IApplication.cpp" /> <ClCompile Include="launcher\IApplication.cpp" />
<ClCompile Include="mathlib\adler32.cpp" /> <ClCompile Include="mathlib\adler32.cpp" />
<ClCompile Include="mathlib\bits.cpp" />
<ClCompile Include="mathlib\crc32.cpp" /> <ClCompile Include="mathlib\crc32.cpp" />
<ClCompile Include="mathlib\IceKey.cpp" /> <ClCompile Include="mathlib\IceKey.cpp" />
<ClCompile Include="networksystem\r5net.cpp" /> <ClCompile Include="networksystem\r5net.cpp" />
@ -362,6 +392,103 @@
<ClCompile Include="squirrel\sqapi.cpp" /> <ClCompile Include="squirrel\sqapi.cpp" />
<ClCompile Include="squirrel\sqinit.cpp" /> <ClCompile Include="squirrel\sqinit.cpp" />
<ClCompile Include="squirrel\sqvm.cpp" /> <ClCompile Include="squirrel\sqvm.cpp" />
<ClCompile Include="thirdparty\detours\src\creatwth.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\detours.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\disasm.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\modules.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp_internal.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp_state.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamdecomp\lzham_lzdecomp.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamdecomp\lzham_lzdecompbase.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_api.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_assert.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_checksum.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_huffman_codes.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_lzbase.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_match_accel.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_mem.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_platform.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_polar_codes.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_prefix_coding.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_pthreads_threading.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_symbol_codec.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_timer.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_vector.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_win32_threading.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="tier0\commandline.cpp" />
<ClCompile Include="tier0\ConCommand.cpp" /> <ClCompile Include="tier0\ConCommand.cpp" />
<ClCompile Include="tier0\completion.cpp" /> <ClCompile Include="tier0\completion.cpp" />
<ClCompile Include="tier0\cvar.cpp" /> <ClCompile Include="tier0\cvar.cpp" />

View File

@ -97,6 +97,18 @@
<Filter Include="sdk\bsplib"> <Filter Include="sdk\bsplib">
<UniqueIdentifier>{8288ba1a-7609-42ef-af3b-850727635a99}</UniqueIdentifier> <UniqueIdentifier>{8288ba1a-7609-42ef-af3b-850727635a99}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="thirdparty\lzham\lzhamcomp">
<UniqueIdentifier>{8736d047-b4af-4c17-99ee-454cc96ec1ba}</UniqueIdentifier>
</Filter>
<Filter Include="thirdparty\lzham\lzhamcomp\include">
<UniqueIdentifier>{e84ad150-2358-4146-971a-02c5f045437c}</UniqueIdentifier>
</Filter>
<Filter Include="thirdparty\lzham\lzhamdecomp">
<UniqueIdentifier>{eb98cd2b-4508-43a0-95e1-feacc7c83a8d}</UniqueIdentifier>
</Filter>
<Filter Include="thirdparty\lzham\lzhamdecomp\include">
<UniqueIdentifier>{463e0739-1e5f-47a0-94d1-6cf5b6bf3ea6}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="client\client.h"> <ClInclude Include="client\client.h">
@ -126,9 +138,6 @@
<ClInclude Include="ebisusdk\EbisuSDK.h"> <ClInclude Include="ebisusdk\EbisuSDK.h">
<Filter>sdk\ebisusdk</Filter> <Filter>sdk\ebisusdk</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="engine\baseclientstate.h">
<Filter>sdk\engine</Filter>
</ClInclude>
<ClInclude Include="engine\host_state.h"> <ClInclude Include="engine\host_state.h">
<Filter>sdk\engine</Filter> <Filter>sdk\engine</Filter>
</ClInclude> </ClInclude>
@ -543,12 +552,6 @@
<ClInclude Include="public\include\binstream.h"> <ClInclude Include="public\include\binstream.h">
<Filter>sdk\public\include</Filter> <Filter>sdk\public\include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_static_lib.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="mathlib\adler32.h"> <ClInclude Include="mathlib\adler32.h">
<Filter>sdk\mathlib</Filter> <Filter>sdk\mathlib</Filter>
</ClInclude> </ClInclude>
@ -567,6 +570,102 @@
<ClInclude Include="windows\system.h"> <ClInclude Include="windows\system.h">
<Filter>windows</Filter> <Filter>windows</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_config.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_core.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_helpers.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_huffman_codes.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_lzbase.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_match_accel.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_math.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_mem.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_null_threading.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_platform.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_polar_codes.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_prefix_coding.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_pthreads_threading.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_static_lib.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_symbol_codec.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_threading.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_timer.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_traits.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_types.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_utils.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_vector.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_win32_threading.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_assert.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_checksum.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\lzhamcomp\lzham_comp.h">
<Filter>thirdparty\lzham\lzhamcomp\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp_internal.h">
<Filter>thirdparty\lzham\lzhamcomp\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\lzhamdecomp\lzham_decomp.h">
<Filter>thirdparty\lzham\lzhamdecomp\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\lzhamdecomp\lzham_lzdecompbase.h">
<Filter>thirdparty\lzham\lzhamdecomp\include</Filter>
</ClInclude>
<ClInclude Include="mathlib\bits.h">
<Filter>sdk\mathlib</Filter>
</ClInclude>
<ClInclude Include="tier0\commandline.h">
<Filter>sdk\tier0</Filter>
</ClInclude>
<ClInclude Include="core\assert.h">
<Filter>core</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="client\IVEngineClient.cpp"> <ClCompile Include="client\IVEngineClient.cpp">
@ -608,9 +707,6 @@
<ClCompile Include="engine\baseclient.cpp"> <ClCompile Include="engine\baseclient.cpp">
<Filter>sdk\engine</Filter> <Filter>sdk\engine</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="engine\baseclientstate.cpp">
<Filter>sdk\engine</Filter>
</ClCompile>
<ClCompile Include="launcher\IApplication.cpp"> <ClCompile Include="launcher\IApplication.cpp">
<Filter>sdk\launcher</Filter> <Filter>sdk\launcher</Filter>
</ClCompile> </ClCompile>
@ -698,6 +794,87 @@
<ClCompile Include="windows\system.cpp"> <ClCompile Include="windows\system.cpp">
<Filter>windows</Filter> <Filter>windows</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="thirdparty\detours\src\detours.cpp">
<Filter>thirdparty\detours</Filter>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\disasm.cpp">
<Filter>thirdparty\detours</Filter>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\modules.cpp">
<Filter>thirdparty\detours</Filter>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\creatwth.cpp">
<Filter>thirdparty\detours</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_assert.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_checksum.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_huffman_codes.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_lzbase.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_match_accel.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_mem.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_platform.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_polar_codes.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_prefix_coding.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_pthreads_threading.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_symbol_codec.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_timer.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_vector.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_win32_threading.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_api.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp.cpp">
<Filter>thirdparty\lzham\lzhamcomp</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp_internal.cpp">
<Filter>thirdparty\lzham\lzhamcomp</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp_state.cpp">
<Filter>thirdparty\lzham\lzhamcomp</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamdecomp\lzham_lzdecomp.cpp">
<Filter>thirdparty\lzham\lzhamdecomp</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamdecomp\lzham_lzdecompbase.cpp">
<Filter>thirdparty\lzham\lzhamdecomp</Filter>
</ClCompile>
<ClCompile Include="mathlib\bits.cpp">
<Filter>sdk\mathlib</Filter>
</ClCompile>
<ClCompile Include="tier0\commandline.cpp">
<Filter>sdk\tier0</Filter>
</ClCompile>
<ClCompile Include="core\logdef.cpp">
<Filter>core</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="r5dev.def" /> <None Include="r5dev.def" />

View File

@ -9,9 +9,9 @@
void HEbisuSDK_Init() void HEbisuSDK_Init()
{ {
#ifdef DEDICATED #ifdef DEDICATED
*(char*)g_bEbisuSDKInitialized.GetPtr() = (char)0x1; // <- 1st EbisuSDK *(char*)g_bEbisuSDKInitialized = (char)0x1; // <- 1st EbisuSDK
*(char*)g_bEbisuSDKCvarInitialized.GetPtr() = (char)0x1; // <- 2nd EbisuSDK *(char*)g_bEbisuSDKCvarInitialized = (char)0x1; // <- 2nd EbisuSDK
*(char*)g_qEbisuSDKCvarInitialized.GetPtr() = (char)0x1; // <- 3rd EbisuSDK *(char*)g_qEbisuSDKCvarInitialized = (char)0x1; // <- 3rd EbisuSDK
#endif // DEDICATED #endif // DEDICATED
} }

View File

@ -6,35 +6,21 @@
namespace namespace
{ {
#ifdef DEDICATED #ifdef DEDICATED
ADDRESS p_EbisuSDK_Init_Tier0 = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x28\x80\x3D\x00\x00\x00\x00\x00\x0F\x85\x00\x02\x00\x00\x48\x89\x5C\x24\x20", "xxxxxx????xxx?xxxxxxxx").GetPtr(); ADDRESS p_EbisuSDK_Init_Tier0 = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x28\x80\x3D\x00\x00\x00\x00\x00\x0F\x85\x00\x02\x00\x00\x48\x89\x5C\x24\x20", "xxxxxx????xxx?xxxxxxxx");
void(*EbisuSDK_Init_Tier0) = (void(*))p_EbisuSDK_Init_Tier0.GetPtr(); /*48 83 EC 28 80 3D ?? ?? ?? ?? 00 0F 85 ?? 02 00 00 48 89 5C 24 20*/ void(*EbisuSDK_Init_Tier0) = (void(*))p_EbisuSDK_Init_Tier0.GetPtr(); /*48 83 EC 28 80 3D ?? ?? ?? ?? 00 0F 85 ?? 02 00 00 48 89 5C 24 20*/
ADDRESS p_EbisuSDK_CVar_Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x57\x48\x83\xEC\x40\x83\x3D", "xxxxxxxx"); ADDRESS p_EbisuSDK_CVar_Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x57\x48\x83\xEC\x40\x83\x3D", "xxxxxxxx");
void(*EbisuSDK_CVar_Init) = (void(*))p_EbisuSDK_CVar_Init.GetPtr(); /*40 57 48 83 EC 40 83 3D*/ void(*EbisuSDK_CVar_Init) = (void(*))p_EbisuSDK_CVar_Init.GetPtr(); /*40 57 48 83 EC 40 83 3D*/
ADDRESS p_EbisuSDK_SetState = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x81\xEC\x00\x00\x00\x00\x80\x3D\x00\x00\x00\x00\x00\x0F\x84\x00\x00\x00\x00\x80\x3D\x00\x00\x00\x00\x00\x74\x5B", "xxx????xx?????xx????xx?????xx"); ADDRESS p_EbisuSDK_SetState = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x81\xEC\x00\x00\x00\x00\x80\x3D\x00\x00\x00\x00\x00\x0F\x84\x00\x00\x00\x00\x80\x3D\x00\x00\x00\x00\x00\x74\x5B", "xxx????xx?????xx????xx?????xx");
void(*EbisuSDK_SetState) = (void(*))p_EbisuSDK_SetState.GetPtr(); /* 48 81 EC ? ? ? ? 80 3D ? ? ? ? ? 0F 84 ? ? ? ? 80 3D ? ? ? ? ? 74 5B */ void(*EbisuSDK_SetState) = (void(*))p_EbisuSDK_SetState.GetPtr(); /*48 81 EC ? ? ? ? 80 3D ? ? ? ? ? 0F 84 ? ? ? ? 80 3D ? ? ? ? ? 74 5B*/
#endif
}
namespace bool* g_bEbisuSDKInitialized = p_EbisuSDK_Init_Tier0.Offset(0x0).FindPatternSelf("80 3D", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast<bool*>();
{ bool* g_bEbisuSDKCvarInitialized = p_EbisuSDK_CVar_Init.Offset(0x12A).FindPatternSelf("C6 05", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast<bool*>();
#ifdef DEDICATED bool* g_qEbisuSDKCvarInitialized = p_EbisuSDK_CVar_Init.Offset(0x20).FindPatternSelf("4C 89 05", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<bool*>();
#if defined (GAMEDLL_S1)
ADDRESS g_bEbisuSDKInitialized = p_EbisuSDK_Init_Tier0.FindPatternSelf("80 3D ?? ?? ?? ?? 00", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).GetPtr();
ADDRESS g_bEbisuSDKCvarInitialized = p_Host_Map_f_CompletionFunc.FindPatternSelf("80 3D 8F 7C 1E 22 00", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).GetPtr();
ADDRESS g_qEbisuSDKCvarInitialized = p_EbisuSDK_CVar_Init.FindPatternSelf("4C 89 05 C4 2B 0E 22", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr();
#elif defined (GAMEDLL_S2)
ADDRESS g_bEbisuSDKInitialized = p_EbisuSDK_Init_Tier0.FindPatternSelf("80 3D ?? ?? ?? ?? 00", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).GetPtr();
ADDRESS g_bEbisuSDKCvarInitialized = p_Host_Map_f_CompletionFunc.FindPatternSelf("80 3D 43 2D 41 22 00", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).GetPtr();
ADDRESS g_qEbisuSDKCvarInitialized = p_EbisuSDK_CVar_Init.FindPatternSelf("4C 89 05 74 2D 32 22", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr();
#elif defined (GAMEDLL_S3)
ADDRESS g_bEbisuSDKInitialized = p_EbisuSDK_Init_Tier0.FindPatternSelf("80 3D ?? ?? ?? ?? 00", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).GetPtr();
ADDRESS g_bEbisuSDKCvarInitialized = p_Host_Map_f_CompletionFunc.FindPatternSelf("80 3D 23 54 2B 23 00", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).GetPtr();
ADDRESS g_qEbisuSDKCvarInitialized = p_EbisuSDK_CVar_Init.FindPatternSelf("4C 89 05 B4 2C 1C 23", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr();
#endif // GAMEDLL_*
#endif // DEDICATED #endif // DEDICATED
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void HEbisuSDK_Init(); void HEbisuSDK_Init();
@ -51,9 +37,9 @@ class HEbisuSDK : public IDetour
std::cout << "| FUN: EbisuSDK_Init_Tier0 : 0x" << std::hex << std::uppercase << p_EbisuSDK_Init_Tier0.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: EbisuSDK_Init_Tier0 : 0x" << std::hex << std::uppercase << p_EbisuSDK_Init_Tier0.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: EbisuSDK_CVar_Init : 0x" << std::hex << std::uppercase << p_EbisuSDK_CVar_Init.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: EbisuSDK_CVar_Init : 0x" << std::hex << std::uppercase << p_EbisuSDK_CVar_Init.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: EbisuSDK_SetState : 0x" << std::hex << std::uppercase << p_EbisuSDK_SetState.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: EbisuSDK_SetState : 0x" << std::hex << std::uppercase << p_EbisuSDK_SetState.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| VAR: g_bEbisuSDKInitialized : 0x" << std::hex << std::uppercase << g_bEbisuSDKInitialized.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| VAR: g_bEbisuSDKInitialized : 0x" << std::hex << std::uppercase << g_bEbisuSDKInitialized << std::setw(0) << " |" << std::endl;
std::cout << "| VAR: g_bEbisuSDKCvarInitialized : 0x" << std::hex << std::uppercase << g_bEbisuSDKCvarInitialized.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| VAR: g_bEbisuSDKCvarInitialized : 0x" << std::hex << std::uppercase << g_bEbisuSDKCvarInitialized << std::setw(0) << " |" << std::endl;
std::cout << "| VAR: g_qEbisuSDKCvarInitialized : 0x" << std::hex << std::uppercase << g_qEbisuSDKCvarInitialized.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| VAR: g_qEbisuSDKCvarInitialized : 0x" << std::hex << std::uppercase << g_qEbisuSDKCvarInitialized << std::setw(0) << " |" << std::endl;
std::cout << "+----------------------------------------------------------------+" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl;
#endif // DEDICATED #endif // DEDICATED
} }

View File

@ -5,5 +5,49 @@
//===========================================================================// //===========================================================================//
#include "core/stdafx.h" #include "core/stdafx.h"
#include "client/cdll_engine_int.h"
#include "engine/debugoverlay.h"
#include "engine/baseclientstate.h" #include "engine/baseclientstate.h"
//TODO
//------------------------------------------------------------------------------
// Purpose: returns true if client simulation is paused
//------------------------------------------------------------------------------
bool CBaseClientState::IsPaused()
{
return *m_bPaused;
}
// Technically doesn't belong here.
//------------------------------------------------------------------------------
// Purpose: gets the client time
//------------------------------------------------------------------------------
float CBaseClientState::GetClientTime()
{
if (*scr_drawloading)
{
return (float)(int)*host_tickcount * (float)*client_debugdraw_int_unk;
}
else
{
return *(float*)client_debugdraw_float_unk;
}
}
//------------------------------------------------------------------------------
// Purpose: gets the client simulation tick count
//------------------------------------------------------------------------------
int CBaseClientState::GetClientTickCount() const
{
return *host_tickcount;
}
//------------------------------------------------------------------------------
// Purpose: sets the client simulation tick count
//------------------------------------------------------------------------------
void CBaseClientState::SetClientTickCount(int tick)
{
*host_tickcount = tick;
}
CBaseClientState* g_pBaseClientState = new CBaseClientState();

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "tier0/basetypes.h" #include "tier0/basetypes.h"
#include "engine/debugoverlay.h"
namespace namespace
{ {
@ -16,6 +17,30 @@ namespace
#endif #endif
} }
namespace
{
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
bool* cl_m_bPaused = p_DrawAllOverlays.Offset(0x90).FindPatternSelf("80 3D ? ? ? 0B ?", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x2).RCast<bool*>();
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
bool* cl_m_bPaused = p_DrawAllOverlays.Offset(0x70).FindPatternSelf("80 3D ? ? ? 01 ?", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x7).RCast<bool*>();
#endif
int* cl_host_tickcount = p_DrawAllOverlays.Offset(0xC0).FindPatternSelf("66 0F 6E", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x4, 0x8).RCast<int*>();
}
///////////////////////////////////////////////////////////////////////////////
class CBaseClientState
{
public:
bool* m_bPaused = cl_m_bPaused; // pauzes the client side simulation in apex.
int* host_tickcount = cl_host_tickcount; // client simulation tick count.
bool IsPaused();
float GetClientTime();
int GetClientTickCount() const; // Get the client tick count.
void SetClientTickCount(int tick); // Set the client tick count.
};
extern CBaseClientState* g_pBaseClientState;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class HClientState : public IDetour class HClientState : public IDetour
@ -23,7 +48,9 @@ class HClientState : public IDetour
virtual void debugp() virtual void debugp()
{ {
//std::cout << "| FUN: CClientState::CheckForResend : 0x" << std::hex << std::uppercase << p_CClientState__CheckForResend.GetPtr() << std::setw(npad) << " |" << std::endl; //std::cout << "| FUN: CClientState::CheckForResend : 0x" << std::hex << std::uppercase << p_CClientState__CheckForResend.GetPtr() << std::setw(npad) << " |" << std::endl;
//std::cout << "+----------------------------------------------------------------+" << std::endl; std::cout << "| VAR: cl_m_bPaused : 0x" << std::hex << std::uppercase << cl_m_bPaused << std::setw(0) << " |" << std::endl;
std::cout << "| FUN: cl_host_tickcount : 0x" << std::hex << std::uppercase << cl_host_tickcount << std::setw(npad) << " |" << std::endl;
std::cout << "+----------------------------------------------------------------+" << std::endl;
} }
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

144
r5dev/engine/debugoverlay.h Normal file
View File

@ -0,0 +1,144 @@
#pragma once
#include "mathlib/vector.h"
#include "mathlib/color.h"
// Something has to be hardcoded..
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) || defined (GAMEDLL_S2)
constexpr auto MATERIALSYSTEM_VCALL_OFF_0 = 0x3F8;
constexpr auto CMATQUEUEDRENDERCONTEXT_VCALL_OFS_0 = 0x278;
constexpr auto CMATQUEUEDRENDERCONTEXT_VCALL_OFS_1 = 0x280;
#elif defined (GAMEDLL_S3)
constexpr auto MATERIALSYSTEM_VCALL_OFF_0 = 0x3F0;
constexpr auto CMATQUEUEDRENDERCONTEXT_VCALL_OFS_0 = 0x288;
constexpr auto CMATQUEUEDRENDERCONTEXT_VCALL_OFS_1 = 0x290;
#endif
constexpr auto CMATQUEUEDRENDERCONTEXT_VCALL_OFS_2 = 0x8;
constexpr auto NDEBUG_PERSIST_TILL_NEXT_SERVER = (0.01023f);
enum class OverlayType_t
{
OVERLAY_BOX = 0,
OVERLAY_SPHERE,
OVERLAY_LINE,
OVERLAY_TRIANGLE,
OVERLAY_SWEPT_BOX,
OVERLAY_BOX2,
OVERLAY_CAPSULE,
OVERLAY_UNK0,
OVERLAY_UNK1
};
struct OverlayBase_t
{
OverlayBase_t()
{
m_Type = OverlayType_t::OVERLAY_BOX;
m_nServerCount = -1;
m_nCreationTick = -1;
m_flEndTime = 0.0f;
m_pNextOverlay = NULL;
unk0 = NULL;
}
bool IsDead();
OverlayType_t m_Type {}; // What type of overlay is it?
int m_nCreationTick{}; // Duration -1 means go away after this frame #
float m_nServerCount {}; // Latch server count, too
float m_flEndTime {}; // When does this box go away
OverlayBase_t* m_pNextOverlay {}; // 16
int64_t unk0 {}; // 24
};
struct OverlayLine_t : public OverlayBase_t
{
OverlayLine_t() { m_Type = OverlayType_t::OVERLAY_LINE; }
Vector3 origin{};
Vector3 dest{};
int r{};
int g{};
int b{};
int a{};
bool noDepthTest{};
};
struct OverlayBox_t : public OverlayBase_t
{
OverlayBox_t() { m_Type = OverlayType_t::OVERLAY_BOX; }
Vector3 origin{};
Vector3 mins{};
Vector3 maxs{};
QAngle angles{};
int r{};
int g{};
int b{};
int a{};
};
void HDestroyOverlay(OverlayBase_t* pOverlay);
void DrawOverlay(OverlayBase_t* pOverlay);
void DebugOverlays_Attach();
void DebugOverlays_Detach();
namespace
{
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
ADDRESS p_DrawAllOverlays = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x55\x48\x83\xEC\x50\x48\x8B\x05\x00\x00\x00\x00", "xxxxxxxxx????");
void (*DrawAllOverlays)(char a1) = (void (*)(char))p_DrawAllOverlays.GetPtr(); /*40 55 48 83 EC 50 48 8B 05 ? ? ? ?*/
ADDRESS p_RenderBox = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x44\x89\x4C\x24\x00", "xxxx?xxxx?xxxx?"); /*48 89 5C 24 ? 48 89 6C 24 ? 44 89 4C 24 ?*/
void* (*RenderBox)(Vector3 origin, QAngle angles, Vector3 vMins, Vector3 vMaxs, Color color, bool bZBuffer) = (void* (*)(Vector3, QAngle, Vector3, Vector3, Color, bool))p_RenderBox.GetPtr();
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
ADDRESS p_DrawAllOverlays = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x55\x48\x83\xEC\x30\x48\x8B\x05\x00\x00\x00\x00\x0F\xB6\xE9", "xxxxxxxxx????xxx");
void (*DrawAllOverlays)(char a1) = (void (*)(char))p_DrawAllOverlays.GetPtr(); /*40 55 48 83 EC 30 48 8B 05 ? ? ? ? 0F B6 E9*/
ADDRESS p_RenderBox = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x44\x89\x4C\x24\x00", "xxxx?xxxx?xxxx?"); /*48 89 5C 24 ? 48 89 6C 24 ? 44 89 4C 24 ?*/
void* (*RenderBox)(Vector3 origin, QAngle angles, Vector3 vMins, Vector3 vMaxs, Color color, bool bZBuffer) = (void* (*)(Vector3, QAngle, Vector3, Vector3, Color, bool))p_RenderBox.GetPtr();
#endif
ADDRESS p_RenderLine = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x74\x24\x00\x44\x89\x44\x24\x00\x57\x41\x56", "xxxx?xxxx?xxx"); /*48 89 74 24 ? 44 89 44 24 ? 57 41 56*/
void* (*RenderLine)(Vector3 origin, Vector3 dest, Color color, bool bZBuffer) = (void* (*)(Vector3, Vector3, Color, bool))p_RenderLine.GetPtr();
ADDRESS p_DestroyOverlay = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x48\x8B\xD9\x48\x8D\x0D\x00\x00\x00\x00\xFF\x15\x00\x00\x00\x00\x48\x63\x03", "xxxxxxxxxxxx????xx????xxx");
void (*DestroyOverlay)(void* pOverlay) = (void (*)(void*))p_DestroyOverlay.GetPtr(); /*40 53 48 83 EC 20 48 8B D9 48 8D 0D ? ? ? ? FF 15 ? ? ? ? 48 63 03 */
int* client_debugdraw_int_unk = p_DrawAllOverlays.Offset(0xC0).FindPatternSelf("F3 0F 59", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x4, 0x8).RCast<int*>();
float* client_debugdraw_float_unk = p_DrawAllOverlays.Offset(0xD0).FindPatternSelf("F3 0F 10", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x4, 0x8).RCast<float*>();
OverlayBase_t** s_pOverlays = p_DrawAllOverlays.Offset(0x10).FindPatternSelf("48 8B 3D", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<OverlayBase_t**>();
LPCRITICAL_SECTION s_OverlayMutex = p_DrawAllOverlays.Offset(0x10).FindPatternSelf("48 8D 0D", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x3, 0x7).RCast<LPCRITICAL_SECTION>();
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
int* render_tickcount = p_DrawAllOverlays.Offset(0x80).FindPatternSelf("3B 0D", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
int* overlay_tickcount = p_DrawAllOverlays.Offset(0x70).FindPatternSelf("3B 0D", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
int* render_tickcount = p_DrawAllOverlays.Offset(0x50).FindPatternSelf("3B 05", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
int* overlay_tickcount = p_DrawAllOverlays.Offset(0x70).FindPatternSelf("3B 05", ADDRESS::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
#endif
}
///////////////////////////////////////////////////////////////////////////////
class HDebugOverlay : public IDetour
{
virtual void debugp()
{
std::cout << "| FUN: DrawAllOverlays : 0x" << std::hex << std::uppercase << p_DrawAllOverlays.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: RenderBox : 0x" << std::hex << std::uppercase << p_RenderBox.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: RenderLine : 0x" << std::hex << std::uppercase << p_RenderLine.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: DestroyOverlay : 0x" << std::hex << std::uppercase << p_DestroyOverlay.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| VAR: s_pOverlays : 0x" << std::hex << std::uppercase << s_pOverlays << std::setw(0) << " |" << std::endl;
std::cout << "| VAR: s_OverlayMutex : 0x" << std::hex << std::uppercase << s_OverlayMutex << std::setw(0) << " |" << std::endl;
std::cout << "| VAR: client_debugdraw_int_unk : 0x" << std::hex << std::uppercase << client_debugdraw_int_unk << std::setw(0) << " |" << std::endl;
std::cout << "| VAR: client_debugdraw_float_unk : 0x" << std::hex << std::uppercase << client_debugdraw_float_unk << std::setw(0) << " |" << std::endl;
std::cout << "| VAR: overlay_tickcount : 0x" << std::hex << std::uppercase << overlay_tickcount << std::setw(0) << " |" << std::endl;
std::cout << "| VAR: render_tickcount : 0x" << std::hex << std::uppercase << render_tickcount << std::setw(0) << " |" << std::endl;
std::cout << "+----------------------------------------------------------------+" << std::endl;
}
};
///////////////////////////////////////////////////////////////////////////////
REGISTER(HDebugOverlay);

View File

@ -10,6 +10,8 @@ namespace
ADDRESS p_Host_Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x48\x89\x7C\x24\x00\x55\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24\x00\x00\x00\x00\xB8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x48\x2B\xE0\x48\x8B\xD9", "xxxx?xxxx?xxxx?xxxxxxxxxxxxx????x????x????xxxxxx"); ADDRESS p_Host_Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x48\x89\x7C\x24\x00\x55\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24\x00\x00\x00\x00\xB8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x48\x2B\xE0\x48\x8B\xD9", "xxxx?xxxx?xxxx?xxxxxxxxxxxxx????x????x????xxxxxx");
void* (*Host_Init)(bool* bDedicated) = (void* (*)(bool*))p_Host_Init.GetPtr(); /*48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? B8 ? ? ? ? E8 ? ? ? ? 48 2B E0 48 8B D9*/ void* (*Host_Init)(bool* bDedicated) = (void* (*)(bool*))p_Host_Init.GetPtr(); /*48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? B8 ? ? ? ? E8 ? ? ? ? 48 2B E0 48 8B D9*/
#endif #endif
ADDRESS p_malloc_internal = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\xE9\x00\x00\x00\x00\xCC\xCC\xCC\x40\x53\x48\x83\xEC\x20\x48\x8D\x05\x00\x00\x00\x00", "x????xxxxxxxxxxxx????");
void* (*malloc_internal)(void* pPool, int64_t size) = (void* (*)(void*, int64_t))p_malloc_internal.GetPtr(); /*E9 ? ? ? ? CC CC CC 40 53 48 83 EC 20 48 8D 05 ? ? ? ?*/
} }
namespace namespace
@ -27,6 +29,7 @@ class HHostCmd : public IDetour
virtual void debugp() virtual void debugp()
{ {
std::cout << "| FUN: Host_Init : 0x" << std::hex << std::uppercase << p_Host_Init.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: Host_Init : 0x" << std::hex << std::uppercase << p_Host_Init.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: malloc_internal : 0x" << std::hex << std::uppercase << p_malloc_internal.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| VAR: g_pMallocPool : 0x" << std::hex << std::uppercase << g_pMallocPool.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| VAR: g_pMallocPool : 0x" << std::hex << std::uppercase << g_pMallocPool.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "+----------------------------------------------------------------+" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl;
} }

View File

@ -1,11 +1,13 @@
#include "core/stdafx.h" #include "core/stdafx.h"
#include "tier0/cvar.h"
#include "tier0/commandline.h"
#include "engine/sys_utils.h" #include "engine/sys_utils.h"
#include "engine/host_state.h" #include "engine/host_state.h"
#include "engine/net_chan.h" #include "engine/net_chan.h"
#include "tier0/cvar.h"
#include "client/IVEngineClient.h" #include "client/IVEngineClient.h"
#include "networksystem/r5net.h" #include "networksystem/r5net.h"
#include "squirrel/sqinit.h" #include "squirrel/sqinit.h"
#include "public/include/bansystem.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: Send keep alive request to Pylon Master Server. // Purpose: Send keep alive request to Pylon Master Server.
@ -13,20 +15,24 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void KeepAliveToPylon() void KeepAliveToPylon()
{ {
if (g_pHostState->m_bActiveGame && sv_pylonvisibility->m_iValue == 1) // Check for active game. if (g_pHostState->m_bActiveGame && sv_pylonvisibility->GetBool()) // Check for active game.
{ {
std::string m_szHostToken = std::string(); std::string m_szHostToken = std::string();
std::string m_szHostRequestMessage = std::string(); std::string m_szHostRequestMessage = std::string();
DevMsg(eDLL_T::CLIENT, "Sending PostServerHost request\n"); DevMsg(eDLL_T::CLIENT, "Sending PostServerHost request\n");
bool result = g_pR5net->PostServerHost(m_szHostRequestMessage, m_szHostToken, bool result = g_pR5net->PostServerHost(m_szHostRequestMessage, m_szHostToken,
ServerListing{ ServerListing{
g_pCvar->FindVar("hostname")->m_pzsCurrentValue, g_pCVar->FindVar("hostname")->GetString(),
std::string(g_pHostState->m_levelName), std::string(g_pHostState->m_levelName),
"", "",
g_pCvar->FindVar("hostport")->m_pzsCurrentValue, g_pCVar->FindVar("hostport")->GetString(),
g_pCvar->FindVar("mp_gamemode")->m_pzsCurrentValue, g_pCVar->FindVar("mp_gamemode")->GetString(),
false, false,
std::to_string(*g_nRemoteFunctionCallsChecksum), // BUG BUG: Checksum is null on dedi
// BUG BUG: Checksum is null on dedi
// ADDITIONAL NOTES: seems to be related to scripts, this also happens when the listen server is started but the client from the same process never connects.
// Checksum only gets set on the server if the client from its own process connects to it.
std::to_string(*g_nRemoteFunctionCallsChecksum),
std::string(), std::string(),
g_szNetKey.c_str() g_szNetKey.c_str()
} }
@ -34,6 +40,66 @@ void KeepAliveToPylon()
} }
} }
//-----------------------------------------------------------------------------
// Purpose: Check refuse list and kill netchan connection.
//-----------------------------------------------------------------------------
void BanListCheck()
{
if (g_pBanSystem->IsRefuseListValid())
{
for (int i = 0; i < g_pBanSystem->vsvrefuseList.size(); i++) // Loop through vector.
{
for (int c = 0; c < MAX_PLAYERS; c++) // Loop through all possible client instances.
{
CClient* client = g_pClient->GetClientInstance(c); // Get client instance.
if (!client)
{
continue;
}
if (!client->GetNetChan()) // Netchan valid?
{
continue;
}
if (g_pClient->m_iOriginID != g_pBanSystem->vsvrefuseList[i].second) // See if nucleus id matches entry.
{
continue;
}
std::string finalIpAddress = std::string();
ADDRESS ipAddressField = ADDRESS(((std::uintptr_t)client->GetNetChan()) + 0x1AC0); // Get client ip from netchan.
if (ipAddressField && ipAddressField.GetValue<int>() != 0x0)
{
std::stringstream ss;
ss << std::to_string(ipAddressField.GetValue<std::uint8_t>()) << "."
<< std::to_string(ipAddressField.Offset(0x1).GetValue<std::uint8_t>()) << "."
<< std::to_string(ipAddressField.Offset(0x2).GetValue<std::uint8_t>()) << "."
<< std::to_string(ipAddressField.Offset(0x3).GetValue<std::uint8_t>());
finalIpAddress = ss.str();
}
DevMsg(eDLL_T::SERVER, "\n");
DevMsg(eDLL_T::SERVER, "______________________________________________________________\n");
DevMsg(eDLL_T::SERVER, "] PYLON NOTICE -----------------------------------------------\n");
DevMsg(eDLL_T::SERVER, "] OriginID : | '%lld' IS GETTING DISCONNECTED.\n", g_pClient->m_iOriginID);
if (finalIpAddress.empty())
DevMsg(eDLL_T::SERVER, "] IP-ADDR : | CLIENT MODIFIED PACKET.\n");
else
DevMsg(eDLL_T::SERVER, "] IP-ADDR : | '%s'\n", finalIpAddress.c_str());
DevMsg(eDLL_T::SERVER, "--------------------------------------------------------------\n");
DevMsg(eDLL_T::SERVER, "\n");
g_pBanSystem->AddEntry(finalIpAddress, g_pClient->m_iOriginID); // Add local entry to reserve a non needed request.
g_pBanSystem->Save(); // Save list.
NET_DisconnectClient(g_pClient, c, g_pBanSystem->vsvrefuseList[i].first.c_str(), 0, 1); // Disconnect client.
}
}
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: state machine's main processing loop // Purpose: state machine's main processing loop
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -64,17 +130,29 @@ void HCHostState_FrameUpdate(void* rcx, void* rdx, float time)
static bool bInitialized = false; static bool bInitialized = false;
if (!bInitialized) if (!bInitialized)
{ {
IConVar_ClearHostNames(); g_pConCommand->Init();
ConCommand_InitConCommand(); g_pConVar->ClearHostNames();
if (!g_pCmdLine->CheckParm("-devsdk"))
{
IVEngineClient_CommandExecute(NULL, "exec autoexec.cfg"); IVEngineClient_CommandExecute(NULL, "exec autoexec.cfg");
IVEngineClient_CommandExecute(NULL, "exec autoexec_server.cfg"); IVEngineClient_CommandExecute(NULL, "exec autoexec_server.cfg");
#ifndef DEDICATED #ifndef DEDICATED
IVEngineClient_CommandExecute(NULL, "exec autoexec_client.cfg"); IVEngineClient_CommandExecute(NULL, "exec autoexec_client.cfg");
#endif // !DEDICATED #endif // !DEDICATED
}
else // Development configs.
{
IVEngineClient_CommandExecute(NULL, "exec autoexec_dev.cfg");
IVEngineClient_CommandExecute(NULL, "exec autoexec_server_dev.cfg");
#ifndef DEDICATED
IVEngineClient_CommandExecute(NULL, "exec autoexec_client_dev.cfg");
#endif // !DEDICATED
}
*(bool*)m_bRestrictServerCommands = true; // Restrict commands. *(bool*)m_bRestrictServerCommands = true; // Restrict commands.
ConCommandBase* disconnect = (ConCommandBase*)g_pCvar->FindCommand("disconnect"); ConCommandBase* disconnect = (ConCommandBase*)g_pCVar->FindCommand("disconnect");
disconnect->AddFlags(FCVAR_SERVER_CAN_EXECUTE); // Make sure server is not restricted to this. disconnect->AddFlags(FCVAR_SERVER_CAN_EXECUTE); // Make sure server is not restricted to this.
static std::thread PylonThread([]() // Pylon request thread. static std::thread PylonThread([]() // Pylon request thread.
@ -86,12 +164,21 @@ void HCHostState_FrameUpdate(void* rcx, void* rdx, float time)
} }
}); });
if (net_userandomkey->m_pParent->m_iValue == 1) static std::thread BanlistThread([]()
{
while (true)
{
BanListCheck();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
});
if (net_userandomkey->GetBool())
{ {
HNET_GenerateKey(); HNET_GenerateKey();
} }
g_pCvar->FindVar("net_usesocketsforloopback")->m_pParent->m_iValue = 1; g_pCVar->FindVar("net_usesocketsforloopback")->SetValue(1);
bInitialized = true; bInitialized = true;
} }
@ -111,6 +198,7 @@ void HCHostState_FrameUpdate(void* rcx, void* rdx, float time)
{ {
Cbuf_ExecuteFn(); Cbuf_ExecuteFn();
oldState = g_pHostState->m_iCurrentState; oldState = g_pHostState->m_iCurrentState;
switch (g_pHostState->m_iCurrentState) switch (g_pHostState->m_iCurrentState)
{ {
case HostStates_t::HS_NEW_GAME: case HostStates_t::HS_NEW_GAME:
@ -159,7 +247,7 @@ void HCHostState_FrameUpdate(void* rcx, void* rdx, float time)
g_pHostState->m_iCurrentState = HostStates_t::HS_RUN; // Set current state to run. g_pHostState->m_iCurrentState = HostStates_t::HS_RUN; // Set current state to run.
// If our next state isn't a shutdown or its a forced shutdown then set next state to run. // If our next state isn't a shutdown or its a forced shutdown then set next state to run.
if (g_pHostState->m_iNextState != HostStates_t::HS_SHUTDOWN || !g_pCvar->FindVar("host_hasIrreversibleShutdown")->m_pParent->m_iValue) if (g_pHostState->m_iNextState != HostStates_t::HS_SHUTDOWN || !g_pCVar->FindVar("host_hasIrreversibleShutdown")->GetBool())
{ {
g_pHostState->m_iNextState = HostStates_t::HS_RUN; g_pHostState->m_iNextState = HostStates_t::HS_RUN;
} }
@ -189,7 +277,7 @@ void HCHostState_FrameUpdate(void* rcx, void* rdx, float time)
g_pHostState->m_iCurrentState = HostStates_t::HS_RUN; // Set current state to run. g_pHostState->m_iCurrentState = HostStates_t::HS_RUN; // Set current state to run.
// If our next state isn't a shutdown or its a forced shutdown then set next state to run. // If our next state isn't a shutdown or its a forced shutdown then set next state to run.
if (g_pHostState->m_iNextState != HostStates_t::HS_SHUTDOWN || !g_pCvar->FindVar("host_hasIrreversibleShutdown")->m_pParent->m_iValue) if (g_pHostState->m_iNextState != HostStates_t::HS_SHUTDOWN || !g_pCVar->FindVar("host_hasIrreversibleShutdown")->GetBool())
{ {
g_pHostState->m_iNextState = HostStates_t::HS_RUN; g_pHostState->m_iNextState = HostStates_t::HS_RUN;
} }
@ -222,7 +310,7 @@ void HCHostState_FrameUpdate(void* rcx, void* rdx, float time)
g_pHostState->m_iCurrentState = HostStates_t::HS_RUN; // Set current state to run. g_pHostState->m_iCurrentState = HostStates_t::HS_RUN; // Set current state to run.
// If our next state isn't a shutdown or its a forced shutdown then set next state to run. // If our next state isn't a shutdown or its a forced shutdown then set next state to run.
if (g_pHostState->m_iNextState != HostStates_t::HS_SHUTDOWN || !g_pCvar->FindVar("host_hasIrreversibleShutdown")->m_pParent->m_iValue) if (g_pHostState->m_iNextState != HostStates_t::HS_SHUTDOWN || !g_pCVar->FindVar("host_hasIrreversibleShutdown")->GetBool())
{ {
g_pHostState->m_iNextState = HostStates_t::HS_RUN; g_pHostState->m_iNextState = HostStates_t::HS_RUN;
} }
@ -262,7 +350,7 @@ void HCHostState_FrameUpdate(void* rcx, void* rdx, float time)
} }
} }
} while ((oldState != HostStates_t::HS_RUN || g_pHostState->m_iNextState == HostStates_t::HS_LOAD_GAME && g_pCvar->FindVar("g_single_frame_shutdown_for_reload_cvar")->m_pParent->m_iValue) } while ((oldState != HostStates_t::HS_RUN || g_pHostState->m_iNextState == HostStates_t::HS_LOAD_GAME && g_pCVar->FindVar("g_single_frame_shutdown_for_reload_cvar")->GetBool())
&& oldState != HostStates_t::HS_SHUTDOWN && oldState != HostStates_t::HS_SHUTDOWN
&& oldState != HostStates_t::HS_RESTART); && oldState != HostStates_t::HS_RESTART);

View File

@ -22,7 +22,9 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void HNET_ShutDown(void* thisptr, const char* szReason, std::uint8_t a1, char a2) void HNET_ShutDown(void* thisptr, const char* szReason, std::uint8_t a1, char a2)
{ {
#ifndef GAMEDLL_S1 // TODO
DownloadPlaylists_f_CompletionFunc(); // Re-load playlist from disk after getting disconnected from the server. DownloadPlaylists_f_CompletionFunc(); // Re-load playlist from disk after getting disconnected from the server.
#endif
NET_Shutdown(thisptr, szReason, a1, a2); NET_Shutdown(thisptr, szReason, a1, a2);
} }
@ -76,7 +78,7 @@ void HNET_SetKey(std::string svNetKey)
void HNET_GenerateKey() void HNET_GenerateKey()
{ {
g_szNetKey.clear(); g_szNetKey.clear();
net_userandomkey->m_pParent->m_iValue = 1; net_userandomkey->SetValue(1);
BCRYPT_ALG_HANDLE hAlgorithm; BCRYPT_ALG_HANDLE hAlgorithm;
if (BCryptOpenAlgorithmProvider(&hAlgorithm, L"RNG", 0, 0) < 0) if (BCryptOpenAlgorithmProvider(&hAlgorithm, L"RNG", 0, 0) < 0)
@ -181,4 +183,4 @@ void CNetChan_Trace_Detach()
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
std::string g_szNetKey = "WDNWLmJYQ2ZlM0VoTid3Yg=="; std::string g_szNetKey = "WDNWLmJYQ2ZlM0VoTid3Yg==";
std::uintptr_t g_pNetKey = g_mGameDll.StringSearch("client:NetEncryption_NewKey").FindPatternSelf("48 8D ? ? ? ? ? 48 3B", ADDRESS::Direction::UP, 150).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr(); std::uintptr_t g_pNetKey = g_mGameDll.StringSearch("client:NetEncryption_NewKey").FindPatternSelf("48 8D ? ? ? ? ? 48 3B", ADDRESS::Direction::UP, 300).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr();

View File

@ -7,7 +7,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int HSys_Error_Internal(char* fmt, va_list args) int HSys_Error_Internal(char* fmt, va_list args)
{ {
printf("\n_____________________________________________________________\n"); printf("\n______________________________________________________________\n");
printf("] ENGINE ERROR ################################################\n"); printf("] ENGINE ERROR ################################################\n");
vprintf(fmt, args); vprintf(fmt, args);

View File

@ -29,7 +29,7 @@ class HSys_Dll2 : public IDetour
{ {
virtual void debugp() virtual void debugp()
{ {
std::cout << "| FUN: CEngineAPI_Connect : 0x" << std::hex << std::uppercase << p_CEngineAPI_Connect.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: CEngineAPI::Connect : 0x" << std::hex << std::uppercase << p_CEngineAPI_Connect.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: PakFile_Init : 0x" << std::hex << std::uppercase << p_PakFile_Init.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: PakFile_Init : 0x" << std::hex << std::uppercase << p_PakFile_Init.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| VAR: g_pMapVPKCache : 0x" << std::hex << std::uppercase << g_pMapVPKCache.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| VAR: g_pMapVPKCache : 0x" << std::hex << std::uppercase << g_pMapVPKCache.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "+----------------------------------------------------------------+" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl;

View File

@ -1,18 +1,23 @@
#include "core/stdafx.h" #include "core/stdafx.h"
#include "core/logdef.h" #include "core/logdef.h"
#include "tier0/commandline.h"
#include "engine/sys_utils.h" #include "engine/sys_utils.h"
#ifndef DEDICATED
#include "vgui/CEngineVGui.h" #include "vgui/CEngineVGui.h"
#include "gameui/IConsole.h" #include "gameui/IConsole.h"
#endif // !DEDICATED
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Sys_Error // Purpose: Exit engine with error
// // Input : *error -
// ... -
// Output : void Sys_Error
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void HSys_Error(char* fmt, ...) void HSys_Error(char* fmt, ...)
{ {
static char buf[1024]; static char buf[1024] = {};
va_list args; va_list args{};
va_start(args, fmt); va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args); vsnprintf(buf, sizeof(buf), fmt, args);
@ -25,39 +30,16 @@ void HSys_Error(char* fmt, ...)
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Sys_Print // Purpose: Show warning in the console, exit engine with error when level 5
// // Input : level -
// *error - ... -
// Output : void* Sys_Warning
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void DevMsg(eDLL_T idx, const char* fmt, ...) void* HSys_Warning(int level, char* fmt, ...)
{ {
int vmIdx = (int)idx; static char buf[1024] = {};
static bool initialized = false;
static char buf[1024];
static std::string vmType[7] = { "Native(S):", "Native(C):", "Native(U):", "Native(E):", "Native(F):", "Native(R):", "Native(M):" }; va_list args{};
static auto iconsole = spdlog::stdout_logger_mt("sys_print_iconsole"); // in-game console.
static auto wconsole = spdlog::stdout_logger_mt("sys_print_wconsole"); // windows console.
static auto sqlogger = spdlog::basic_logger_mt("sys_print_logger", "platform\\logs\\sys_print.log"); // file logger.
std::string vmStr = vmType[vmIdx].c_str();
g_spd_sys_w_oss.str("");
g_spd_sys_w_oss.clear();
if (!initialized)
{
iconsole = std::make_shared<spdlog::logger>("sys_print_ostream", g_spd_sys_p_ostream_sink);
iconsole->set_pattern("[%S.%e] %v");
iconsole->set_level(spdlog::level::debug);
wconsole->set_pattern("[%S.%e] %v");
wconsole->set_level(spdlog::level::debug);
sqlogger->set_pattern("[%S.%e] %v");
sqlogger->set_level(spdlog::level::debug);
initialized = true;
}
va_list args;
va_start(args, fmt); va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args); vsnprintf(buf, sizeof(buf), fmt, args);
@ -65,24 +47,65 @@ void DevMsg(eDLL_T idx, const char* fmt, ...)
buf[sizeof(buf) - 1] = 0; buf[sizeof(buf) - 1] = 0;
va_end(args); va_end(args);
DevMsg(eDLL_T::NONE, "Warning(%d)%s\n", level, buf); // TODO: Color
return Sys_Warning(level, buf);
}
//-----------------------------------------------------------------------------
// Purpose: Show logs to all console interfaces
// Input : idx -
// *fmt - ... -
// Output : void DevMsg
//-----------------------------------------------------------------------------
void DevMsg(eDLL_T idx, const char* fmt, ...)
{
static char buf[1024] = {};
static std::shared_ptr<spdlog::logger> iconsole = spdlog::get("game_console");
static std::shared_ptr<spdlog::logger> wconsole = spdlog::get("win_console");
static std::shared_ptr<spdlog::logger> sqlogger = spdlog::get("dev_message_logger");
{/////////////////////////////
va_list args{};
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
buf[sizeof(buf) - 1] = 0;
va_end(args);
}/////////////////////////////
std::string vmStr = sDLL_T[(int)idx].c_str();
vmStr.append(buf); vmStr.append(buf);
iconsole->debug(vmStr);
wconsole->debug(vmStr);
sqlogger->debug(vmStr); sqlogger->debug(vmStr);
if (!g_bSpdLog_UseAnsiClr) { wconsole->debug(vmStr); }
else
{
std::string vmStrAnsi = sANSI_DLL_T[(int)idx].c_str();
vmStrAnsi.append(buf);
wconsole->debug(vmStrAnsi);
}
#ifndef DEDICATED #ifndef DEDICATED
g_spd_sys_w_oss.str("");
g_spd_sys_w_oss.clear();
iconsole->info(vmStr);
std::string s = g_spd_sys_w_oss.str(); std::string s = g_spd_sys_w_oss.str();
const char* c = s.c_str();
g_pLogSystem.AddLog((LogType_t)eDLL_T::ENGINE, s); g_pLogSystem.AddLog((LogType_t)eDLL_T::ENGINE, s);
Items.push_back(Strdup((const char*)c)); g_pIConsole->m_ivConLog.push_back(Strdup(s.c_str()));
#endif // !DEDICATED #endif // !DEDICATED
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Sys_LoadAssetHelper // Purpose: Load assets from a custom directory if file exists
// // Input : *lpFileName -
// a2 - *a3 -
// Output : void* Sys_LoadAssetHelper
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void* HSys_LoadAssetHelper(const CHAR* lpFileName, std::int64_t a2, LARGE_INTEGER* a3) void* HSys_LoadAssetHelper(const CHAR* lpFileName, std::int64_t a2, LARGE_INTEGER* a3)
{ {
@ -113,11 +136,13 @@ void* HSys_LoadAssetHelper(const CHAR* lpFileName, std::int64_t a2, LARGE_INTEGE
void SysUtils_Attach() void SysUtils_Attach()
{ {
DetourAttach((LPVOID*)&Sys_Error, &HSys_Error); DetourAttach((LPVOID*)&Sys_Error, &HSys_Error);
DetourAttach((LPVOID*)&Sys_Warning, &HSys_Warning);
DetourAttach((LPVOID*)&Sys_LoadAssetHelper, &HSys_LoadAssetHelper); DetourAttach((LPVOID*)&Sys_LoadAssetHelper, &HSys_LoadAssetHelper);
} }
void SysUtils_Detach() void SysUtils_Detach()
{ {
DetourDetach((LPVOID*)&Sys_Error, &HSys_Error); DetourDetach((LPVOID*)&Sys_Error, &HSys_Error);
DetourDetach((LPVOID*)&Sys_Warning, &HSys_Warning);
DetourDetach((LPVOID*)&Sys_LoadAssetHelper, &HSys_LoadAssetHelper); DetourDetach((LPVOID*)&Sys_LoadAssetHelper, &HSys_LoadAssetHelper);
} }

View File

@ -7,11 +7,17 @@ namespace
ADDRESS p_Sys_Error = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x4C\x24\x08\x48\x89\x54\x24\x10\x4C\x89\x44\x24\x18\x4C\x89\x4C\x24\x20\x53\x55\x41\x54\x41\x56\xB8\x58\x10\x00\x00\xE8", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); ADDRESS p_Sys_Error = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x4C\x24\x08\x48\x89\x54\x24\x10\x4C\x89\x44\x24\x18\x4C\x89\x4C\x24\x20\x53\x55\x41\x54\x41\x56\xB8\x58\x10\x00\x00\xE8", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
void (*Sys_Error)(char* fmt, ...) = (void (*)(char* fmt, ...))p_Sys_Error.GetPtr(); /*48 89 4C 24 08 48 89 54 24 10 4C 89 44 24 18 4C 89 4C 24 20 53 55 41 54 41 56 B8 58 10 00 00 E8*/ void (*Sys_Error)(char* fmt, ...) = (void (*)(char* fmt, ...))p_Sys_Error.GetPtr(); /*48 89 4C 24 08 48 89 54 24 10 4C 89 44 24 18 4C 89 4C 24 20 53 55 41 54 41 56 B8 58 10 00 00 E8*/
ADDRESS p_Warning = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x54\x24\x00\x4C\x89\x44\x24\x00\x4C\x89\x4C\x24\x00\x48\x83\xEC\x28\x4C\x8D\x44\x24\x00\xE8\x00\x00\x00\x00\x48\x83\xC4\x28\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x48\x89\x7C\x24\x00\x8B\x05\x00\x00\x00\x00", "xxxx?xxxx?xxxx?xxxxxxxx?x????xxxxxxxxxxxxxxxxxxxxxxx?xxxx?xxxx?xx????");
void* (*Sys_Warning)(int level, char* fmt, ...) = (void* (*)(int, char* fmt, ...))p_Warning.GetPtr(); /*48 89 54 24 ? 4C 89 44 24 ? 4C 89 4C 24 ? 48 83 EC 28 4C 8D 44 24 ? E8 ? ? ? ? 48 83 C4 28 C3 CC CC CC CC CC CC CC CC CC CC CC CC CC CC 48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 8B 05 ? ? ? ?*/
ADDRESS p_Sys_LoadAssetHelper = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x74\x24\x10\x48\x89\x7C\x24\x18\x41\x56\x48\x83\xEC\x40\x33", "xxxxxxxxxxxxxxxxx"); ADDRESS p_Sys_LoadAssetHelper = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x74\x24\x10\x48\x89\x7C\x24\x18\x41\x56\x48\x83\xEC\x40\x33", "xxxxxxxxxxxxxxxxx");
void*(*Sys_LoadAssetHelper)(const CHAR* lpFileName, std::int64_t a2, LARGE_INTEGER* a3) = (void*(*)(const CHAR*, std::int64_t, LARGE_INTEGER*))p_Sys_LoadAssetHelper.GetPtr();/*48 89 74 24 10 48 89 7C 24 18 41 56 48 83 EC 40 33*/ void*(*Sys_LoadAssetHelper)(const CHAR* lpFileName, std::int64_t a2, LARGE_INTEGER* a3) = (void*(*)(const CHAR*, std::int64_t, LARGE_INTEGER*))p_Sys_LoadAssetHelper.GetPtr();/*48 89 74 24 10 48 89 7C 24 18 41 56 48 83 EC 40 33*/
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) || defined (GAMEDLL_S2) #if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
ADDRESS p_MemAlloc_Wrapper = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x48\x8B\x05\x00\x00\x00\x00\x48\x8B\xD9\x48\x85\xC0\x75\x0C\xE8\x16", "xxxxxxxxx????xxxxxxxxxx"); ADDRESS p_MemAlloc_Wrapper = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x48\x8B\x05\x00\x00\x00\x00\x48\x8B\xD9\x48\x85\xC0\x75\x0C\xE8\x16", "xxxxxxxxx????xxxxxxxxxx");
void* (*MemAlloc_Wrapper)(std::int64_t size) = (void* (*)(std::int64_t))p_MemAlloc_Wrapper.GetPtr(); /*40 53 48 83 EC 20 48 8B 05 ?? ?? ?? ?? 48 8B D9 48 85 C0 75 0C E8 16*/ void* (*MemAlloc_Wrapper)(std::int64_t size) = (void* (*)(std::int64_t))p_MemAlloc_Wrapper.GetPtr(); /*40 53 48 83 EC 20 48 8B 05 ?? ?? ?? ?? 48 8B D9 48 85 C0 75 0C E8 16*/
#elif defined (GAMEDLL_S2)
ADDRESS p_MemAlloc_Wrapper = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x48\x8B\x05\x00\x00\x00\x00\x48\x8B\xD9\x48\x85\xC0\x75\x0C\xE8\x00\x00\x00\x00\x48\x89\x05\x00\x00\x00\x00\x4C\x8B\x00\x48\x8B\xD3\x48\x8B\xC8\x48\x83\xC4\x20\x5B\x49\xFF\x60\x08", "xxxxxxxxx????xxxxxxxxx????xxx????xxxxxxxxxxxxxxxxxx");
void* (*MemAlloc_Wrapper)(std::int64_t size) = (void* (*)(std::int64_t))p_MemAlloc_Wrapper.GetPtr(); /*40 53 48 83 EC 20 48 8B 05 ? ? ? ? 48 8B D9 48 85 C0 75 0C E8 ? ? ? ? 48 89 05 ? ? ? ? 4C 8B 00 48 8B D3 48 8B C8 48 83 C4 20 5B 49 FF 60 08 */
#elif defined (GAMEDLL_S3) #elif defined (GAMEDLL_S3)
ADDRESS p_MemAlloc_Wrapper = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x48\x8B\x05\x6B\x83\x25\x0D\x48\x8B\xD9", "xxxxxxxxxxxxxxxx"); ADDRESS p_MemAlloc_Wrapper = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x48\x8B\x05\x6B\x83\x25\x0D\x48\x8B\xD9", "xxxxxxxxxxxxxxxx");
void* (*MemAlloc_Wrapper)(std::int64_t size) = (void* (*)(std::int64_t))p_MemAlloc_Wrapper.GetPtr(); /*40 53 48 83 EC 20 48 8B 05 6B 83 25 0D 48 8B D9*/ void* (*MemAlloc_Wrapper)(std::int64_t size) = (void* (*)(std::int64_t))p_MemAlloc_Wrapper.GetPtr(); /*40 53 48 83 EC 20 48 8B 05 6B 83 25 0D 48 8B D9*/
@ -27,7 +33,32 @@ enum class eDLL_T : int
ENGINE = 3, // Wrapper ENGINE = 3, // Wrapper
FS = 4, // File System FS = 4, // File System
RTECH = 5, // RTech API RTECH = 5, // RTech API
MS = 6 // Material System MS = 6, // Material System
NONE = 7
};
const std::string sDLL_T[8] =
{
"Native(S):",
"Native(C):",
"Native(U):",
"Native(E):",
"Native(F):",
"Native(R):",
"Native(M):",
""
};
const static std::string sANSI_DLL_T[8] =
{
"\u001b[94mNative(S):",
"\u001b[90mNative(C):",
"\u001b[33mNative(U):",
"\u001b[37mNative(E):",
"\u001b[96mNative(F):",
"\u001b[92mNative(R):",
"\u001b[91mNative(M):",
""
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -43,6 +74,7 @@ class HSys_Utils : public IDetour
virtual void debugp() virtual void debugp()
{ {
std::cout << "| FUN: Sys_Error : 0x" << std::hex << std::uppercase << p_Sys_Error.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: Sys_Error : 0x" << std::hex << std::uppercase << p_Sys_Error.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: Sys_Warning : 0x" << std::hex << std::uppercase << p_Warning.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: Sys_LoadAssetHelper : 0x" << std::hex << std::uppercase << p_Sys_LoadAssetHelper.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: Sys_LoadAssetHelper : 0x" << std::hex << std::uppercase << p_Sys_LoadAssetHelper.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: MemAlloc_Wrapper : 0x" << std::hex << std::uppercase << p_MemAlloc_Wrapper.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: MemAlloc_Wrapper : 0x" << std::hex << std::uppercase << p_MemAlloc_Wrapper.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "+----------------------------------------------------------------+" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl;

View File

@ -1,17 +1,9 @@
#include "core/stdafx.h"
#include "core/init.h"
#include "tier0/cvar.h"
#include "windows/id3dx.h"
#include "windows/console.h"
#include "gameui/IConsole.h"
#include "client/IVEngineClient.h"
/****************************************************************************** /******************************************************************************
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
File : IConsole.cpp File : IConsole.cpp
Date : 18:07:2021 Date : 18:07:2021
Author : Kawe Mazidjatari Author : Kawe Mazidjatari
Purpose: Implements the in-game console frontend Purpose: Implements the in-game console front-end
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
History: History:
- 15:06:2021 | 14:56 : Created by Kawe Mazidjatari - 15:06:2021 | 14:56 : Created by Kawe Mazidjatari
@ -20,6 +12,14 @@ History:
******************************************************************************/ ******************************************************************************/
#include "core/stdafx.h"
#include "core/init.h"
#include "tier0/cvar.h"
#include "windows/id3dx.h"
#include "windows/console.h"
#include "gameui/IConsole.h"
#include "client/IVEngineClient.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: // Purpose:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -31,12 +31,11 @@ CConsole::CConsole()
m_nHistoryPos = -1; m_nHistoryPos = -1;
m_bAutoScroll = true; m_bAutoScroll = true;
m_bScrollToBottom = false; m_bScrollToBottom = false;
m_bThemeSet = false; m_bInitialized = false;
m_ivCommands.push_back("CLEAR"); m_ivCommands.push_back("CLEAR");
m_ivCommands.push_back("HELP"); m_ivCommands.push_back("HELP");
m_ivCommands.push_back("HISTORY"); m_ivCommands.push_back("HISTORY");
AddLog("[DEBUG] THREAD ID: %ld\n", g_dThreadId);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -54,21 +53,24 @@ CConsole::~CConsole()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: draws the console frontend // Purpose: draws the console frontend
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CConsole::Draw(const char* title, bool* bDraw) void CConsole::Draw(const char* pszTitle, bool* bDraw)
{ {
bool copy_to_clipboard = false; if (!m_bInitialized)
static auto iConsoleConfig = &g_pImGuiConfig->IConsole_Config;
static auto iBrowserConfig = &g_pImGuiConfig->IBrowser_Config;
if (!m_bThemeSet)
{ {
SetStyleVar(); SetStyleVar();
m_bThemeSet = true; m_bInitialized = true;
} }
if (iConsoleConfig->m_bAutoClear && Items.Size > iConsoleConfig->m_nAutoClearLimit) // Check if Auto-Clear is enabled and if its above our limit. if (g_pImGuiConfig->IConsole_Config.m_bAutoClear) // Check if Auto-Clear is enabled.
{ {
ClearLog(); // Loop and clear the beginning of the vector until we are below our limit.
m_ivHistory.clear(); while (m_ivConLog.Size > g_pImGuiConfig->IConsole_Config.m_nAutoClearLimit)
{
m_ivConLog.erase(m_ivConLog.begin());
}
while (m_ivHistory.Size > 512)
{
m_ivHistory.erase(m_ivHistory.begin());
}
} }
//ImGui::ShowStyleEditor(); //ImGui::ShowStyleEditor();
@ -76,14 +78,14 @@ void CConsole::Draw(const char* title, bool* bDraw)
ImGui::SetNextWindowSize(ImVec2(1000, 600), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(1000, 600), ImGuiCond_FirstUseEver);
ImGui::SetWindowPos(ImVec2(-1000, 50), ImGuiCond_FirstUseEver); ImGui::SetWindowPos(ImVec2(-1000, 50), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(title, bDraw)) if (!ImGui::Begin(pszTitle, bDraw))
{ {
ImGui::End(); ImGui::End();
return; return;
} }
if (*bDraw == NULL) if (!*bDraw)
{ {
g_bShowConsole = false; m_bActivate = false;
} }
// Reserve enough left-over height and width for 1 separator + 1 input text // Reserve enough left-over height and width for 1 separator + 1 input text
@ -94,9 +96,83 @@ void CConsole::Draw(const char* title, bool* bDraw)
ImGui::Separator(); ImGui::Separator();
if (ImGui::BeginPopup("Options")) if (ImGui::BeginPopup("Options"))
{ {
Options();
}
if (ImGui::Button("Options"))
{
ImGui::OpenPopup("Options");
}
ImGui::SameLine();
m_itFilter.Draw("Filter [\"-incl,-excl\"] [\"error\"]", footer_width_to_reserve - 500);
ImGui::Separator();
///////////////////////////////////////////////////////////////////////
ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), true, ImGuiWindowFlags_AlwaysVerticalScrollbar);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 4.f, 6.f });
if (m_bCopyToClipBoard) { ImGui::LogToClipboard(); }
ColorLog();
if (m_bCopyToClipBoard)
{
ImGui::LogToClipboard();
ImGui::LogFinish();
m_bCopyToClipBoard = false;
}
if (m_bScrollToBottom || (m_bAutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
{
ImGui::SetScrollHereY(1.0f);
m_bScrollToBottom = false;
}
///////////////////////////////////////////////////////////////////////
ImGui::PopStyleVar();
ImGui::EndChild();
ImGui::Separator();
ImGui::PushItemWidth(footer_width_to_reserve - 80);
if (ImGui::IsWindowAppearing()) { ImGui::SetKeyboardFocusHere(); }
ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
if (ImGui::InputText("##input", m_szInputBuf, IM_ARRAYSIZE(m_szInputBuf), input_text_flags, &TextEditCallbackStub, (void*)this))
{
if (m_szInputBuf[0]) { ProcessCommand(m_szInputBuf); }
strcpy_s(m_szInputBuf, 1, "");
m_bReclaimFocus = true;
}
ImGui::SameLine();
if (ImGui::Button("Submit"))
{
if (m_szInputBuf[0]) { ProcessCommand(m_szInputBuf); }
strcpy_s(m_szInputBuf, 1, "");
m_bReclaimFocus = true;
}
// Auto-focus on window apparition.
ImGui::SetItemDefaultFocus();
// Auto focus previous widget.
if (m_bReclaimFocus)
{
ImGui::SetKeyboardFocusHere();
m_bReclaimFocus = false;
}
ImGui::End();
}
//-----------------------------------------------------------------------------
// Purpose: draws the options panel
//-----------------------------------------------------------------------------
void CConsole::Options()
{
ImGui::Checkbox("Auto-Scroll", &m_bAutoScroll); ImGui::Checkbox("Auto-Scroll", &m_bAutoScroll);
if (ImGui::Checkbox("Auto-Clear", &iConsoleConfig->m_bAutoClear)) if (ImGui::Checkbox("Auto-Clear", &g_pImGuiConfig->IConsole_Config.m_bAutoClear))
{ {
g_pImGuiConfig->Save(); g_pImGuiConfig->Save();
} }
@ -104,7 +180,7 @@ void CConsole::Draw(const char* title, bool* bDraw)
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushItemWidth(100); ImGui::PushItemWidth(100);
if (ImGui::InputInt("Limit##AutoClearAfterCertainIndexCGameConsole", &iConsoleConfig->m_nAutoClearLimit)) if (ImGui::InputInt("Limit##AutoClearFirstIConsole", &g_pImGuiConfig->IConsole_Config.m_nAutoClearLimit))
{ {
g_pImGuiConfig->Save(); g_pImGuiConfig->Save();
} }
@ -117,12 +193,12 @@ void CConsole::Draw(const char* title, bool* bDraw)
} }
ImGui::SameLine(); ImGui::SameLine();
copy_to_clipboard = ImGui::SmallButton("Copy"); m_bCopyToClipBoard = ImGui::SmallButton("Copy");
ImGui::Text("Console Hotkey:"); ImGui::Text("Console Hotkey:");
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Hotkey("##OpenIConsoleBind0", &iConsoleConfig->m_nBind0, ImVec2(80, 80))) if (ImGui::Hotkey("##OpenIConsoleBind0", &g_pImGuiConfig->IConsole_Config.m_nBind0, ImVec2(80, 80)))
{ {
g_pImGuiConfig->Save(); g_pImGuiConfig->Save();
} }
@ -130,158 +206,22 @@ void CConsole::Draw(const char* title, bool* bDraw)
ImGui::Text("Browser Hotkey:"); ImGui::Text("Browser Hotkey:");
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Hotkey("##OpenIBrowserBind0", &iBrowserConfig->m_nBind0, ImVec2(80, 80))) if (ImGui::Hotkey("##OpenIBrowserBind0", &g_pImGuiConfig->IBrowser_Config.m_nBind0, ImVec2(80, 80)))
{ {
g_pImGuiConfig->Save(); g_pImGuiConfig->Save();
} }
ImGui::EndPopup(); ImGui::EndPopup();
}
if (ImGui::Button("Options"))
{
ImGui::OpenPopup("Options");
}
ImGui::SameLine();
m_itFilter.Draw("Filter [\"-incl,-excl\"] [\"error\"]", footer_width_to_reserve - 500);
ImGui::Separator();
///////////////////////////////////////////////////////////////////////
ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), true, ImGuiWindowFlags_AlwaysVerticalScrollbar);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{ 4.f, 6.f });
if (copy_to_clipboard)
{
ImGui::LogToClipboard();
}
for (int i = 0; i < Items.Size; i++)
{
const char* item = Items[i];
if (!m_itFilter.PassFilter(item))
{
continue;
}
///////////////////////////////////////////////////////////////////
ImVec4 color;
bool has_color = false;
///////////////////////////////////////////////////////////////////
// General
if (strstr(item, "[INFO]")) { color = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); has_color = true; }
if (strstr(item, "[ERROR]")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
if (strstr(item, "[DEBUG]")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; }
if (strstr(item, "[WARNING]")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; }
if (strncmp(item, "# ", 2) == 0) { color = ImVec4(1.00f, 0.80f, 0.60f, 1.00f); has_color = true; }
///////////////////////////////////////////////////////////////////
// Script virtual machines per game dll
if (strstr(item, "Script(S):")) { color = ImVec4(0.59f, 0.58f, 0.73f, 1.00f); has_color = true; }
if (strstr(item, "Script(C):")) { color = ImVec4(0.59f, 0.58f, 0.63f, 1.00f); has_color = true; }
if (strstr(item, "Script(U):")) { color = ImVec4(0.59f, 0.48f, 0.53f, 1.00f); has_color = true; }
///////////////////////////////////////////////////////////////////
// Native per game dll
if (strstr(item, "Native(S):")) { color = ImVec4(0.59f, 0.58f, 0.73f, 1.00f); has_color = true; }
if (strstr(item, "Native(C):")) { color = ImVec4(0.59f, 0.58f, 0.63f, 1.00f); has_color = true; }
if (strstr(item, "Native(U):")) { color = ImVec4(0.59f, 0.48f, 0.53f, 1.00f); has_color = true; }
///////////////////////////////////////////////////////////////////
// Native per sys dll
if (strstr(item, "Native(E):")) { color = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); has_color = true; }
if (strstr(item, "Native(F):")) { color = ImVec4(0.32f, 0.64f, 0.72f, 1.00f); has_color = true; }
if (strstr(item, "Native(R):")) { color = ImVec4(0.36f, 0.70f, 0.35f, 1.00f); has_color = true; }
if (strstr(item, "Native(M):")) { color = ImVec4(0.75f, 0.41f, 0.67f, 1.00f); has_color = true; }
///////////////////////////////////////////////////////////////////
// Callbacks
//if (strstr(item, "CodeCallback_")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; }
///////////////////////////////////////////////////////////////////
// Squirrel VM script errors
if (strstr(item, ".gnut")) { color = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); has_color = true; }
if (strstr(item, ".nut")) { color = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); has_color = true; }
if (strstr(item, "[CLIENT]")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
if (strstr(item, "[SERVER]")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
if (strstr(item, "[UI]")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
if (strstr(item, "SCRIPT ERROR")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
if (strstr(item, "SCRIPT COMPILE")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
if (strstr(item, ".gnut #")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
if (strstr(item, ".nut #")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
if (strstr(item, "): -> ")) { color = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); has_color = true; }
///////////////////////////////////////////////////////////////////
// Squirrel VM script debug
if (strstr(item, "CALLSTACK")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; }
if (strstr(item, "LOCALS")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; }
if (strstr(item, "*FUNCTION")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; }
if (strstr(item, "DIAGPRINTS")) { color = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); has_color = true; }
if (strstr(item, " File : ")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; }
if (strstr(item, "<><>GRX<><>")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; }
///////////////////////////////////////////////////////////////////
// Filters
//if (strstr(item, ") -> ")) { color = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); has_color = true; }
if (has_color) { ImGui::PushStyleColor(ImGuiCol_Text, color); }
ImGui::TextWrapped(item);
if (has_color) { ImGui::PopStyleColor(); }
}
if (copy_to_clipboard) { ImGui::LogFinish(); }
if (m_bScrollToBottom || (m_bAutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())) { ImGui::SetScrollHereY(1.0f); }
m_bScrollToBottom = false;
///////////////////////////////////////////////////////////////////////
ImGui::PopStyleVar();
ImGui::EndChild();
ImGui::Separator();
///////////////////////////////////////////////////////////////////////
// Console
bool reclaim_focus = false;
ImGui::PushItemWidth(footer_width_to_reserve - 80);
if (ImGui::IsWindowAppearing()) { ImGui::SetKeyboardFocusHere(); }
ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
if (ImGui::InputText("##input", m_szInputBuf, IM_ARRAYSIZE(m_szInputBuf), input_text_flags, &TextEditCallbackStub, (void*)this))
{
char* s = m_szInputBuf;
const char* replace = "";
if (strstr(m_szInputBuf, "`")) { strcpy_s(s, sizeof(replace), replace); }
Strtrim(s);
if (s[0]) { ProcessCommand(s); }
strcpy_s(s, sizeof(replace), replace);
reclaim_focus = true;
}
ImGui::SameLine();
if (ImGui::Button("Submit"))
{
char* s = m_szInputBuf;
const char* replace = "";
if (s[0]) { ProcessCommand(s); }
strcpy_s(s, sizeof(replace), replace);
reclaim_focus = true;
}
// Auto-focus on window apparition.
ImGui::SetItemDefaultFocus();
// Auto focus previous widget.
if (reclaim_focus)
{
ImGui::SetKeyboardFocusHere(-1);
}
ImGui::End();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: executes submitted commands in a separate thread // Purpose: executes submitted commands in a separate thread
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CConsole::ProcessCommand(const char* command_line) void CConsole::ProcessCommand(const char* pszCommand)
{ {
AddLog("# %s\n", command_line); AddLog("# %s\n", pszCommand);
std::thread t(IVEngineClient_CommandExecute, this, command_line); std::thread t(IVEngineClient_CommandExecute, this, pszCommand);
t.detach(); // Detach from render thread. t.detach(); // Detach from render thread.
// This is to avoid a race condition. // This is to avoid a race condition.
@ -290,7 +230,7 @@ void CConsole::ProcessCommand(const char* command_line)
m_nHistoryPos = -1; m_nHistoryPos = -1;
for (int i = m_ivHistory.Size - 1; i >= 0; i--) for (int i = m_ivHistory.Size - 1; i >= 0; i--)
{ {
if (Stricmp(m_ivHistory[i], command_line) == 0) if (Stricmp(m_ivHistory[i], pszCommand) == 0)
{ {
delete m_ivHistory[i]; delete m_ivHistory[i];
m_ivHistory.erase(m_ivHistory.begin() + i); m_ivHistory.erase(m_ivHistory.begin() + i);
@ -298,34 +238,34 @@ void CConsole::ProcessCommand(const char* command_line)
} }
} }
m_ivHistory.push_back(Strdup(command_line)); m_ivHistory.push_back(Strdup(pszCommand));
if (Stricmp(command_line, "CLEAR") == 0) if (Stricmp(pszCommand, "CLEAR") == 0)
{ {
ClearLog(); ClearLog();
} }
else if (Stricmp(command_line, "HELP") == 0) else if (Stricmp(pszCommand, "HELP") == 0)
{ {
AddLog("Frontend commands:"); AddLog("Commands:");
for (int i = 0; i < m_ivCommands.Size; i++) for (int i = 0; i < m_ivCommands.Size; i++)
{ {
AddLog("- %s", m_ivCommands[i]); AddLog("- %s", m_ivCommands[i]);
} }
AddLog("Log types:"); AddLog("Log types:");
AddLog("Script(S): = Server (Script VM)"); AddLog("Script(S): = Server DLL (Script VM)");
AddLog("Script(C): = Client (Script VM)"); AddLog("Script(C): = Client DLL (Script VM)");
AddLog("Script(U): = UI (Script VM)"); AddLog("Script(U): = UI DLL (Script VM)");
AddLog("Native(S): = Server dll (Code)"); AddLog("Native(S): = Server DLL (Code)");
AddLog("Native(C): = Client dll (code)"); AddLog("Native(C): = Client DLL (Code)");
AddLog("Native(U): = UI dll (code)"); AddLog("Native(U): = UI DLL (Code)");
AddLog("Native(E): = Engine dll (code)"); AddLog("Native(E): = Engine DLL (Code)");
AddLog("Native(F): = FileSystem dll (code)"); AddLog("Native(F): = FileSys DLL (Code)");
AddLog("Native(R): = RTech dll (code)"); AddLog("Native(R): = RTech DLL (Code)");
AddLog("Native(M): = MaterialSystem dll (code)"); AddLog("Native(M): = MatSys DLL (Code)");
} }
else if (Stricmp(command_line, "HISTORY") == 0) else if (Stricmp(pszCommand, "HISTORY") == 0)
{ {
int first = m_ivHistory.Size - 10; int first = m_ivHistory.Size - 10;
for (int i = first > 0 ? first : 0; i < m_ivHistory.Size; i++) for (int i = first > 0 ? first : 0; i < m_ivHistory.Size; i++)
@ -347,22 +287,22 @@ int CConsole::TextEditCallback(ImGuiInputTextCallbackData* data)
case ImGuiInputTextFlags_CallbackCompletion: case ImGuiInputTextFlags_CallbackCompletion:
{ {
// Locate beginning of current word. // Locate beginning of current word.
const char* word_end = data->Buf + data->CursorPos; const char* pszWordEnd = data->Buf + data->CursorPos;
const char* word_start = word_end; const char* pszWordStart = pszWordEnd;
while (word_start > data->Buf) while (pszWordStart > data->Buf)
{ {
const char c = word_start[-1]; const char c = pszWordStart[-1];
if (c == ' ' || c == '\t' || c == ',' || c == ';') if (c == ' ' || c == '\t' || c == ',' || c == ';')
{ {
break; break;
} }
word_start--; pszWordStart--;
} }
break; break;
} }
case ImGuiInputTextFlags_CallbackHistory: case ImGuiInputTextFlags_CallbackHistory:
{ {
const int prev_history_pos = m_nHistoryPos; const int nPrevHistoryPos = m_nHistoryPos;
if (data->EventKey == ImGuiKey_UpArrow) if (data->EventKey == ImGuiKey_UpArrow)
{ {
if (m_nHistoryPos == -1) { m_nHistoryPos = m_ivHistory.Size - 1; } if (m_nHistoryPos == -1) { m_nHistoryPos = m_ivHistory.Size - 1; }
@ -378,31 +318,180 @@ int CConsole::TextEditCallback(ImGuiInputTextCallbackData* data)
} }
} }
} }
if (prev_history_pos != m_nHistoryPos) if (nPrevHistoryPos != m_nHistoryPos)
{ {
const char* history_str = (m_nHistoryPos >= 0) ? m_ivHistory[m_nHistoryPos] : ""; const char* pszHistory = (m_nHistoryPos >= 0) ? m_ivHistory[m_nHistoryPos] : "";
data->DeleteChars(0, data->BufTextLen); data->DeleteChars(0, data->BufTextLen);
data->InsertChars(0, history_str); data->InsertChars(0, pszHistory);
} }
} }
} }
return 0; return 0;
} }
//############################################################################# //-----------------------------------------------------------------------------
// ENTRYPOINT // Purpose: text edit callback stub
//############################################################################# //-----------------------------------------------------------------------------
int CConsole::TextEditCallbackStub(ImGuiInputTextCallbackData* data)
CConsole* g_GameConsole = nullptr;
void DrawConsole(bool* bDraw)
{ {
static CConsole console; CConsole* pConsole = (CConsole*)data->UserData;
static bool AssignPtr = []() return pConsole->TextEditCallback(data);
{
g_GameConsole = &console;
return true;
} ();
console.Draw("Console", bDraw);
} }
/////////////////////////////////////////////////////////////////////////// //-----------------------------------------------------------------------------
// Purpose: adds logs to the vector
//-----------------------------------------------------------------------------
void CConsole::AddLog(const char* fmt, ...) IM_FMTARGS(2)
{
char buf[1024];
va_list args;
va_start(args, fmt);
vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
buf[IM_ARRAYSIZE(buf) - 1] = 0;
va_end(args);
m_ivConLog.push_back(Strdup(buf));
}
//-----------------------------------------------------------------------------
// Purpose: clears the entire vector
//-----------------------------------------------------------------------------
void CConsole::ClearLog()
{
for (int i = 0; i < m_ivConLog.Size; i++) { free(m_ivConLog[i]); }
m_ivConLog.clear();
}
//-----------------------------------------------------------------------------
// Purpose: colors important logs
//-----------------------------------------------------------------------------
void CConsole::ColorLog()
{
for (int i = 0; i < m_ivConLog.Size; i++)
{
const char* pszConLog = m_ivConLog[i];
if (!m_itFilter.PassFilter(pszConLog))
{
continue;
}
///////////////////////////////////////////////////////////////////////
ImVec4 imColor;
// General
if (strstr(pszConLog, "[INFO]")) { imColor = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); true; }
if (strstr(pszConLog, "[ERROR]")) { imColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); true; }
if (strstr(pszConLog, "[DEBUG]")) { imColor = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); true; }
if (strstr(pszConLog, "[WARNING]")) { imColor = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); true; }
if (strncmp(pszConLog, "# ", 2) == 0) { imColor = ImVec4(1.00f, 0.80f, 0.60f, 1.00f); true; }
// Script virtual machines per game dll
if (strstr(pszConLog, "Script(S):")) { imColor = ImVec4(0.59f, 0.58f, 0.73f, 1.00f); true; }
if (strstr(pszConLog, "Script(C):")) { imColor = ImVec4(0.59f, 0.58f, 0.63f, 1.00f); true; }
if (strstr(pszConLog, "Script(U):")) { imColor = ImVec4(0.59f, 0.48f, 0.53f, 1.00f); true; }
if (strstr(pszConLog, "Script(X):")) { imColor = ImVec4(0.59f, 0.58f, 0.63f, 1.00f); true; }
// Native per game dll
if (strstr(pszConLog, "Native(S):")) { imColor = ImVec4(0.59f, 0.58f, 0.73f, 1.00f); true; }
if (strstr(pszConLog, "Native(C):")) { imColor = ImVec4(0.59f, 0.58f, 0.63f, 1.00f); true; }
if (strstr(pszConLog, "Native(U):")) { imColor = ImVec4(0.59f, 0.48f, 0.53f, 1.00f); true; }
// Native per sys dll
if (strstr(pszConLog, "Native(E):")) { imColor = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); true; }
if (strstr(pszConLog, "Native(F):")) { imColor = ImVec4(0.32f, 0.64f, 0.72f, 1.00f); true; }
if (strstr(pszConLog, "Native(R):")) { imColor = ImVec4(0.36f, 0.70f, 0.35f, 1.00f); true; }
if (strstr(pszConLog, "Native(M):")) { imColor = ImVec4(0.75f, 0.41f, 0.67f, 1.00f); true; }
// Callbacks
//if (strstr(item, "CodeCallback_")) { color = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); has_color = true; }
// Squirrel VM script errors
if (strstr(pszConLog, ".gnut")) { imColor = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); true; }
if (strstr(pszConLog, ".nut")) { imColor = ImVec4(1.00f, 1.00f, 1.00f, 0.60f); true; }
if (strstr(pszConLog, "[CLIENT]")) { imColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); true; }
if (strstr(pszConLog, "[SERVER]")) { imColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); true; }
if (strstr(pszConLog, "[UI]")) { imColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); true; }
if (strstr(pszConLog, "SCRIPT ERROR")) { imColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); true; }
if (strstr(pszConLog, "SCRIPT COMPILE")) { imColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); true; }
if (strstr(pszConLog, ".gnut #")) { imColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); true; }
if (strstr(pszConLog, ".nut #")) { imColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); true; }
if (strstr(pszConLog, "): -> ")) { imColor = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); true; }
// Squirrel VM script debug
if (strstr(pszConLog, "CALLSTACK")) { imColor = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); true; }
if (strstr(pszConLog, "LOCALS")) { imColor = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); true; }
if (strstr(pszConLog, "*FUNCTION")) { imColor = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); true; }
if (strstr(pszConLog, "DIAGPRINTS")) { imColor = ImVec4(1.00f, 1.00f, 0.00f, 0.80f); true; }
if (strstr(pszConLog, " File : ")) { imColor = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); true; }
if (strstr(pszConLog, "<><>GRX<><>")) { imColor = ImVec4(0.00f, 0.30f, 1.00f, 1.00f); true; }
// Filters
//if (strstr(item, ") -> ")) { color = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); has_color = true; }
ImGui::PushStyleColor(ImGuiCol_Text, imColor);
ImGui::TextWrapped(pszConLog);
ImGui::PopStyleColor();
}
}
//-----------------------------------------------------------------------------
// Purpose: sets the console front-end style
//-----------------------------------------------------------------------------
void CConsole::SetStyleVar()
{
ImGuiStyle& imStyle = ImGui::GetStyle();
ImVec4* imColor = imStyle.Colors;
imColor[ImGuiCol_Text] = ImVec4(0.81f, 0.81f, 0.81f, 1.00f);
imColor[ImGuiCol_TextDisabled] = ImVec4(0.56f, 0.56f, 0.56f, 1.00f);
imColor[ImGuiCol_WindowBg] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f);
imColor[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
imColor[ImGuiCol_PopupBg] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f);
imColor[ImGuiCol_Border] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
imColor[ImGuiCol_BorderShadow] = ImVec4(0.04f, 0.04f, 0.04f, 0.64f);
imColor[ImGuiCol_FrameBg] = ImVec4(0.13f, 0.13f, 0.13f, 1.00f);
imColor[ImGuiCol_FrameBgHovered] = ImVec4(0.19f, 0.19f, 0.19f, 1.00f);
imColor[ImGuiCol_FrameBgActive] = ImVec4(0.24f, 0.24f, 0.24f, 1.00f);
imColor[ImGuiCol_TitleBg] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f);
imColor[ImGuiCol_TitleBgActive] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f);
imColor[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
imColor[ImGuiCol_MenuBarBg] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f);
imColor[ImGuiCol_ScrollbarBg] = ImVec4(0.10f, 0.10f, 0.10f, 1.00f);
imColor[ImGuiCol_ScrollbarGrab] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
imColor[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
imColor[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.63f, 0.63f, 0.63f, 1.00f);
imColor[ImGuiCol_CheckMark] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
imColor[ImGuiCol_SliderGrab] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
imColor[ImGuiCol_SliderGrabActive] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
imColor[ImGuiCol_Button] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f);
imColor[ImGuiCol_ButtonHovered] = ImVec4(0.45f, 0.45f, 0.45f, 1.00f);
imColor[ImGuiCol_ButtonActive] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f);
imColor[ImGuiCol_Header] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f);
imColor[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.45f, 1.00f);
imColor[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
imColor[ImGuiCol_Separator] = ImVec4(0.53f, 0.53f, 0.57f, 1.00f);
imColor[ImGuiCol_SeparatorHovered] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
imColor[ImGuiCol_SeparatorActive] = ImVec4(0.63f, 0.63f, 0.63f, 1.00f);
imColor[ImGuiCol_ResizeGrip] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
imColor[ImGuiCol_ResizeGripHovered] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f);
imColor[ImGuiCol_ResizeGripActive] = ImVec4(0.63f, 0.63f, 0.63f, 1.00f);
imColor[ImGuiCol_Tab] = ImVec4(0.18f, 0.18f, 0.18f, 1.00f);
imColor[ImGuiCol_TabHovered] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
imColor[ImGuiCol_TabActive] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
imStyle.WindowBorderSize = 0.0f;
imStyle.FrameBorderSize = 1.0f;
imStyle.ChildBorderSize = 1.0f;
imStyle.PopupBorderSize = 1.0f;
imStyle.TabBorderSize = 1.0f;
imStyle.WindowRounding = 2.5f;
imStyle.FrameRounding = 0.0f;
imStyle.ChildRounding = 0.0f;
imStyle.PopupRounding = 0.0f;
imStyle.TabRounding = 1.0f;
imStyle.ScrollbarRounding = 1.0f;
imStyle.ItemSpacing = ImVec2(4, 4);
imStyle.WindowPadding = ImVec2(5, 5);
}
CConsole* g_pIConsole = new CConsole();

View File

@ -1,124 +1,44 @@
#pragma once #pragma once
#ifndef DEDICATED #ifndef DEDICATED
///////////////////////////////////////////////////////////////////////////////
// Initialization
void DrawConsole(bool* bDraw);
///////////////////////////////////////////////////////////////////////////////
// Globals
inline ImVector<char*> Items;
class CConsole class CConsole
{ {
private: private:
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
char m_szInputBuf[256] = { 0 }; char m_szInputBuf[512] = { 0 };
ImVector<const char*> m_ivCommands; ImVector<const char*> m_ivCommands;
ImVector<char*> m_ivHistory; ImVector<char*> m_ivHistory;
int m_nHistoryPos = -1; int m_nHistoryPos = -1;
ImGuiTextFilter m_itFilter; ImGuiTextFilter m_itFilter;
bool m_bAutoScroll = true; bool m_bAutoScroll = true;
bool m_bScrollToBottom = false; bool m_bScrollToBottom = false;
bool m_bThemeSet = false; bool m_bCopyToClipBoard = false;
bool m_bReclaimFocus = false;
bool m_bInitialized = false;
public: public:
/////////////////////////////////////////////////////////////////////////// bool m_bActivate = false;
ImVector<char*> m_ivConLog;
///////////////////////////////////////////////////////////////////////////
CConsole(); CConsole();
~CConsole(); ~CConsole();
void Draw(const char* title, bool* bDraw); void Draw(const char* title, bool* bDraw);
void Options();
void ProcessCommand(const char* command_line); void ProcessCommand(const char* command_line);
int TextEditCallback(ImGuiInputTextCallbackData* data); int TextEditCallback(ImGuiInputTextCallbackData* data);
static int TextEditCallbackStub(ImGuiInputTextCallbackData* data);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// History void AddLog(const char* fmt, ...) IM_FMTARGS(2);
static int TextEditCallbackStub(ImGuiInputTextCallbackData* data) void ClearLog();
{ void ColorLog();
CConsole* console = (CConsole*)data->UserData;
return console->TextEditCallback(data);
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Utility void SetStyleVar();
void ClearLog()
{
for (int i = 0; i < Items.Size; i++) { free(Items[i]); }
Items.clear();
}
void AddLog(const char* fmt, ...) IM_FMTARGS(2)
{
char buf[1024];
va_list args;
va_start(args, fmt);
vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
buf[IM_ARRAYSIZE(buf) - 1] = 0;
va_end(args);
Items.push_back(Strdup(buf));
}
///////////////////////////////////////////////////////////////////////
// Style
void SetStyleVar()
{
ImGuiStyle& style = ImGui::GetStyle();
ImVec4* colors = style.Colors;
colors[ImGuiCol_Text] = ImVec4(0.81f, 0.81f, 0.81f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.56f, 0.56f, 0.56f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f);
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f);
colors[ImGuiCol_Border] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
colors[ImGuiCol_BorderShadow] = ImVec4(0.04f, 0.04f, 0.04f, 0.64f);
colors[ImGuiCol_FrameBg] = ImVec4(0.13f, 0.13f, 0.13f, 1.00f);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.19f, 0.19f, 0.19f, 1.00f);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.24f, 0.24f, 0.24f, 1.00f);
colors[ImGuiCol_TitleBg] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f);
colors[ImGuiCol_TitleBgActive] = ImVec4(0.27f, 0.27f, 0.27f, 1.00f);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.10f, 0.10f, 0.10f, 1.00f);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.63f, 0.63f, 0.63f, 1.00f);
colors[ImGuiCol_CheckMark] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
colors[ImGuiCol_SliderGrab] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
colors[ImGuiCol_Button] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f);
colors[ImGuiCol_ButtonHovered] = ImVec4(0.45f, 0.45f, 0.45f, 1.00f);
colors[ImGuiCol_ButtonActive] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f);
colors[ImGuiCol_Header] = ImVec4(0.35f, 0.35f, 0.35f, 1.00f);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.45f, 1.00f);
colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
colors[ImGuiCol_Separator] = ImVec4(0.53f, 0.53f, 0.57f, 1.00f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.63f, 0.63f, 0.63f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.63f, 0.63f, 0.63f, 1.00f);
colors[ImGuiCol_Tab] = ImVec4(0.18f, 0.18f, 0.18f, 1.00f);
colors[ImGuiCol_TabHovered] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
colors[ImGuiCol_TabActive] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
style.WindowBorderSize = 0.0f;
style.FrameBorderSize = 1.0f;
style.ChildBorderSize = 1.0f;
style.PopupBorderSize = 1.0f;
style.TabBorderSize = 1.0f;
style.WindowRounding = 2.5f;
style.FrameRounding = 0.0f;
style.ChildRounding = 0.0f;
style.PopupRounding = 0.0f;
style.TabRounding = 1.0f;
style.ScrollbarRounding = 1.0f;
style.ItemSpacing = ImVec2(4, 4);
style.WindowPadding = ImVec2(5, 5);
}
}; };
extern CConsole* g_GameConsole; ///////////////////////////////////////////////////////////////////////////////
extern CConsole* g_pIConsole;
#endif // !DEDICATED #endif // !DEDICATED

View File

@ -3,10 +3,14 @@
namespace namespace
{ {
#if defined (GAMEDLL_S1) || defined (GAMEDLL_S1)
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
/* ==== CAPPSYSTEMGROUP ================================================================================================================================================= */ /* ==== CAPPSYSTEMGROUP ================================================================================================================================================= */
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
ADDRESS p_IAppSystem_Main = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x28\x80\xB9\x00\x00\x00\x00\x00\x48\x8B\x15\x00\x00\x00\x00", "xxxxxx?????xxx????");
void* (*IAppSystem_Main)(void* a1, void* a2) = (void* (*)(void*, void*))p_IAppSystem_Main.GetPtr(); /*48 83 EC 28 80 B9 ?? ?? ?? ?? ?? 48 8B 15 ?? ?? ?? ?? */
ADDRESS p_IAppSystem_Create = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x8B\xC4\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x60\x48\xC7\x40\x00\x00\x00\x00\x00\x48\x89\x58\x08", "xxxxxxxxxxxxxxxxxxx?????xxxx");
bool (*IAppSystem_Create)(void* a1) = (bool(*)(void*))p_IAppSystem_Create.GetPtr(); /*48 8B C4 57 41 54 41 55 41 56 41 57 48 83 EC 60 48 C7 40 ?? ?? ?? ?? ?? 48 89 58 08*/
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
ADDRESS p_IAppSystem_Main = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x80\xB9\x00\x00\x00\x00\x00\xBB\x00\x00\x00\x00", "xxxxxxxx?????x????"); ADDRESS p_IAppSystem_Main = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x80\xB9\x00\x00\x00\x00\x00\xBB\x00\x00\x00\x00", "xxxxxxxx?????x????");
void* (*IAppSystem_Main)(void* a1, void* a2) = (void* (*)(void*, void*))p_IAppSystem_Main.GetPtr(); /*40 53 48 83 EC 20 80 B9 ?? ?? ?? ?? ?? BB ?? ?? ?? ??*/ void* (*IAppSystem_Main)(void* a1, void* a2) = (void* (*)(void*, void*))p_IAppSystem_Main.GetPtr(); /*40 53 48 83 EC 20 80 B9 ?? ?? ?? ?? ?? BB ?? ?? ?? ??*/

View File

@ -0,0 +1,39 @@
#pragma once
#include "engine/debugoverlay.h"
namespace
{
/* ==== MATERIALSYSTEM ================================================================================================================================================== */
ADDRESS CMaterialSystem__Init = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x70\x48\x83\x3D\x00\x00\x00\x00\x00", "xxxx?xxxxxxxxxxxxxxxxxx?????");
// 0x1403BBFD0 // 48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 70 48 83 3D ? ? ? ? ? //
ADDRESS InitMaterialSystem = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x28\x48\x8B\x0D\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x48\x8B\x01\xFF\x90\x00\x00\x00\x00\x48\x8B\x0D\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\x48\x8B\x01\xFF\x90\x00\x00\x00\x00", "xxxxxxx????xxx????xxxxx????xxx????xxx????xxxxx????"); //
// 0x14024B390 // 48 83 EC 28 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? 48 8B 01 FF 90 ? ? ? ? 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? 48 8B 01 FF 90 ? ? ? ? //
ADDRESS p_DrawStreamOverlay = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x41\x56\xB8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x48\x2B\xE0\xC6\x02\x00", "xxx????x????xxxxxx"); // 41 56 B8 ? ? ? ? E8 ? ? ? ? 48 2B E0 C6 02 00 //
const char* (*DrawStreamOverlay)(void* thisptr, std::uint8_t* a2, void* unused, void* a4) = (const char* (*)(void*, std::uint8_t*, void*, void*))p_DrawStreamOverlay.GetPtr();
void* g_pMaterialSystem = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x8B\x0D\x00\x00\x00\x00\x48\x85\xC9\x74\x11\x48\x8B\x01\x48\x8D\x15\x00\x00\x00\x00", "xxx????xxxxxxxxxxx????").ResolveRelativeAddressSelf(0x3, 0x7).RCast<void*>();
int* total_streaming_tex_memory = p_DrawStreamOverlay.Offset(0x0).FindPatternSelf("48 8B 05", ADDRESS::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).RCast<int*>();
int* unfree_streaming_tex_memory = p_DrawStreamOverlay.Offset(0x20).FindPatternSelf("48 8B 05", ADDRESS::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).RCast<int*>();
int* unusable_streaming_tex_memory = p_DrawStreamOverlay.Offset(0x50).FindPatternSelf("48 8B 05", ADDRESS::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).RCast<int*>();
}
///////////////////////////////////////////////////////////////////////////////
class HMaterialSystem : public IDetour
{
virtual void debugp()
{
std::cout << "| FUN: CMaterialSystem::Init : 0x" << std::hex << std::uppercase << CMaterialSystem__Init.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: InitMaterialSystem : 0x" << std::hex << std::uppercase << InitMaterialSystem.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: DrawStreamOverlay : 0x" << std::hex << std::uppercase << p_DrawStreamOverlay.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| VAR: g_pMaterialSystem : 0x" << std::hex << std::uppercase << g_pMaterialSystem << std::setw(0) << " |" << std::endl;
std::cout << "+----------------------------------------------------------------+" << std::endl;
}
};
///////////////////////////////////////////////////////////////////////////////
void DebugOverlays_Attach();
REGISTER(HMaterialSystem);

46
r5dev/mathlib/bits.cpp Normal file
View File

@ -0,0 +1,46 @@
//=============================================================================//
//
// Purpose: look for NANs, infinities, and underflows.
//
//=============================================================================//
#include "core/stdafx.h"
#include "mathlib/bits.h"
//-----------------------------------------------------------------------------
// This follows the ANSI/IEEE 754-1985 standard
//-----------------------------------------------------------------------------
unsigned long& FloatBits(float& f)
{
return *reinterpret_cast<unsigned long*>(&f);
}
unsigned long const& FloatBits(float const& f)
{
return *reinterpret_cast<unsigned long const*>(&f);
}
float BitsToFloat(unsigned long i)
{
return *reinterpret_cast<float*>(&i);
}
bool IsFinite(float f)
{
return ((FloatBits(f) & 0x7F800000) != 0x7F800000);
}
unsigned long FloatAbsBits(float f)
{
return FloatBits(f) & 0x7FFFFFFF;
}
float FloatMakePositive(float f)
{
return fabsf(f);
}
float FloatNegate(float f)
{
return -f; //BitsToFloat( FloatBits(f) ^ 0x80000000 );
}

10
r5dev/mathlib/bits.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
unsigned long& FloatBits(float& f);
unsigned long const& FloatBits(float const& f);
float BitsToFloat(unsigned long i);
bool IsFinite(float f);
unsigned long FloatAbsBits(float f);
#define FLOAT32_NAN_BITS (std::uint32_t)0x7FC00000 // NaN!
#define FLOAT32_NAN BitsToFloat( FLOAT32_NAN_BITS )

14
r5dev/mathlib/color.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
class Color
{
public:
Color(int r, int g, int b, int a)
{
_color[0] = (unsigned char)r;
_color[1] = (unsigned char)g;
_color[2] = (unsigned char)b;
_color[3] = (unsigned char)a;
}
unsigned char _color[4];
};

View File

@ -0,0 +1,21 @@
#pragma once
namespace
{
/* ==== WASAPI THREAD SERVICE =========================================================================================================================================== */
ADDRESS p_WASAPI_GetAudioDevice = g_mRadAudioSystemDll.FindPatternSIMD((std::uint8_t*)"\x48\x8B\xC4\x48\x89\x58\x20\x55\x56\x41\x54", "xxxxxxxxxxx");
// 0x18005AD10 // 48 8B C4 48 89 58 20 55 56 41 54 //
}
///////////////////////////////////////////////////////////////////////////////
class HWASAPIServiceThread : public IDetour
{
virtual void debugp()
{
std::cout << "| FUN: WASAPI_GetAudioDevice : 0x" << std::hex << std::uppercase << p_WASAPI_GetAudioDevice.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "+----------------------------------------------------------------+" << std::endl;
}
};
///////////////////////////////////////////////////////////////////////////////
REGISTER(HWASAPIServiceThread);

View File

@ -81,7 +81,11 @@ void CBanSystem::AddEntry(std::string svIpAddress, std::int64_t nOriginID)
{ {
if (!svIpAddress.empty() && nOriginID > 0) // Check if args are valid. if (!svIpAddress.empty() && nOriginID > 0) // Check if args are valid.
{ {
vsvBanList.push_back(std::make_pair(svIpAddress, nOriginID)); // Push it back into the vector. auto it = std::find(vsvBanList.begin(), vsvBanList.end(), std::make_pair(svIpAddress, nOriginID)); // Check if we have this entry already.
if (it == vsvBanList.end()) // We don't have that entry?
{
vsvBanList.push_back(std::make_pair(svIpAddress, nOriginID)); // Add it.
}
} }
} }
@ -102,19 +106,19 @@ void CBanSystem::DeleteEntry(std::string svIpAddress, std::int64_t nOriginID)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: adds a connect refuse entry to the refuselist // Purpose: adds a connect refuse entry to the refuselist
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CBanSystem::AddConnectionRefuse(std::string svError, int nUserID) void CBanSystem::AddConnectionRefuse(std::string svError, std::int64_t nOriginID)
{ {
if (vsvrefuseList.empty()) if (vsvrefuseList.empty())
{ {
vsvrefuseList.push_back(std::make_pair(svError, nUserID)); vsvrefuseList.push_back(std::make_pair(svError, nOriginID));
} }
else else
{ {
for (int i = 0; i < vsvrefuseList.size(); i++) // Loop through vector. for (int i = 0; i < vsvrefuseList.size(); i++) // Loop through vector.
{ {
if (vsvrefuseList[i].second != nUserID) // Do any entries match our vector? if (vsvrefuseList[i].second != nOriginID) // Do any entries match our vector?
{ {
vsvrefuseList.push_back(std::make_pair(svError, nUserID)); // Push it back into the vector. vsvrefuseList.push_back(std::make_pair(svError, nOriginID)); // Push it back into the vector.
} }
} }
} }
@ -123,11 +127,11 @@ void CBanSystem::AddConnectionRefuse(std::string svError, int nUserID)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Purpose: deletes an entry in the refuselist // Purpose: deletes an entry in the refuselist
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CBanSystem::DeleteConnectionRefuse(int nUserID) void CBanSystem::DeleteConnectionRefuse(std::int64_t nOriginID)
{ {
for (int i = 0; i < vsvrefuseList.size(); i++) // Loop through vector. for (int i = 0; i < vsvrefuseList.size(); i++) // Loop through vector.
{ {
if (vsvrefuseList[i].second == nUserID) // Do any entries match our vector? if (vsvrefuseList[i].second == nOriginID) // Do any entries match our vector?
{ {
vsvrefuseList.erase(vsvrefuseList.begin() + i); // If so erase that vector element. vsvrefuseList.erase(vsvrefuseList.begin() + i); // If so erase that vector element.
} }

View File

@ -10,13 +10,13 @@ public:
void Save(); void Save();
void AddEntry(std::string svIpAddress, std::int64_t nOriginID); void AddEntry(std::string svIpAddress, std::int64_t nOriginID);
void DeleteEntry(std::string svIpAddress, std::int64_t nOriginID); void DeleteEntry(std::string svIpAddress, std::int64_t nOriginID);
void AddConnectionRefuse(std::string svError, int nUserID); void AddConnectionRefuse(std::string svError, std::int64_t nOriginID);
void DeleteConnectionRefuse(int nUserID); void DeleteConnectionRefuse(std::int64_t nUserID);
bool IsBanned(std::string svIpAddress, std::int64_t nOriginID); bool IsBanned(std::string svIpAddress, std::int64_t nOriginID);
bool IsRefuseListValid(); bool IsRefuseListValid();
bool IsBanListValid(); bool IsBanListValid();
std::vector<std::pair<std::string, int>> vsvrefuseList = {};; std::vector<std::pair<std::string, std::int64_t>> vsvrefuseList = {};;
private: private:
std::vector<std::pair<std::string, std::int64_t>> vsvBanList = {}; std::vector<std::pair<std::string, std::int64_t>> vsvBanList = {};
}; };

View File

@ -3,6 +3,7 @@
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Internals // Internals
BOOL IsBadReadPtrV2(void* ptr);
BOOL FileExists(const char* szPath); BOOL FileExists(const char* szPath);
MODULEINFO GetModuleInfo(const char* szModule); MODULEINFO GetModuleInfo(const char* szModule);
DWORD64 FindPatternSIMD(const char* szModule, const unsigned char* szPattern, const char* szMask); DWORD64 FindPatternSIMD(const char* szModule, const unsigned char* szPattern, const char* szMask);

View File

@ -13,6 +13,22 @@ BOOL FileExists(const char* szPath)
return std::filesystem::exists(szPath); return std::filesystem::exists(szPath);
} }
///////////////////////////////////////////////////////////////////////////////
// For checking if pointer is valid or bad.
BOOL IsBadReadPtrV2(void* ptr)
{
MEMORY_BASIC_INFORMATION mbi = { 0 };
if (::VirtualQuery(ptr, &mbi, sizeof(mbi)))
{
DWORD mask = (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY);
bool b = !(mbi.Protect & mask);
// check the page is not a guard page
if (mbi.Protect & (PAGE_GUARD | PAGE_NOACCESS)) b = true;
return b;
}
return true;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// For getting information about the executing module. // For getting information about the executing module.
MODULEINFO GetModuleInfo(const char* szModule) MODULEINFO GetModuleInfo(const char* szModule)
@ -132,7 +148,7 @@ void HexDump(const char* szHeader, int nFunc, const void* pData, int nSize)
szAscii[16] = '\0'; szAscii[16] = '\0';
// Add new loggers here to replace the placeholder. // Add new loggers here to replace the placeholder.
if (nFunc == 0) { logger = g_spd_netchan_logger; } if (nFunc == 0) { logger = spdlog::get("netchan_pack_logger"); }
// Add timestamp. // Add timestamp.
logger->set_level(spdlog::level::trace); logger->set_level(spdlog::level::trace);

View File

@ -26,6 +26,7 @@
<ClCompile Include="common\opcodes.cpp" /> <ClCompile Include="common\opcodes.cpp" />
<ClCompile Include="core\dllmain.cpp" /> <ClCompile Include="core\dllmain.cpp" />
<ClCompile Include="core\init.cpp" /> <ClCompile Include="core\init.cpp" />
<ClCompile Include="core\logdef.cpp" />
<ClCompile Include="core\stdafx.cpp"> <ClCompile Include="core\stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
@ -44,6 +45,7 @@
<ClCompile Include="inputsystem\inputsystem.cpp" /> <ClCompile Include="inputsystem\inputsystem.cpp" />
<ClCompile Include="launcher\IApplication.cpp" /> <ClCompile Include="launcher\IApplication.cpp" />
<ClCompile Include="mathlib\adler32.cpp" /> <ClCompile Include="mathlib\adler32.cpp" />
<ClCompile Include="mathlib\bits.cpp" />
<ClCompile Include="mathlib\crc32.cpp" /> <ClCompile Include="mathlib\crc32.cpp" />
<ClCompile Include="mathlib\IceKey.cpp" /> <ClCompile Include="mathlib\IceKey.cpp" />
<ClCompile Include="networksystem\r5net.cpp" /> <ClCompile Include="networksystem\r5net.cpp" />
@ -57,7 +59,24 @@
<ClCompile Include="server\server.cpp" /> <ClCompile Include="server\server.cpp" />
<ClCompile Include="squirrel\sqapi.cpp" /> <ClCompile Include="squirrel\sqapi.cpp" />
<ClCompile Include="squirrel\sqinit.cpp" /> <ClCompile Include="squirrel\sqinit.cpp" />
<ClCompile Include="squirrel\sqnativefunctions.cpp" />
<ClCompile Include="squirrel\sqvm.cpp" /> <ClCompile Include="squirrel\sqvm.cpp" />
<ClCompile Include="thirdparty\detours\src\creatwth.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\detours.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\disasm.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\modules.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\imgui\src\imgui.cpp"> <ClCompile Include="thirdparty\imgui\src\imgui.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
@ -87,13 +106,94 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="thirdparty\imgui\src\imgui_utility.cpp"> <ClCompile Include="thirdparty\imgui\src\imgui_utility.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Use</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Use</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="thirdparty\imgui\src\imgui_widgets.cpp"> <ClCompile Include="thirdparty\imgui\src\imgui_widgets.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp_internal.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp_state.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamdecomp\lzham_lzdecomp.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamdecomp\lzham_lzdecompbase.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_api.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_assert.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_checksum.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_huffman_codes.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_lzbase.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_match_accel.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_mem.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_platform.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_polar_codes.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_prefix_coding.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_pthreads_threading.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_symbol_codec.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_timer.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_vector.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_win32_threading.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="tier0\commandline.cpp" />
<ClCompile Include="tier0\ConCommand.cpp" /> <ClCompile Include="tier0\ConCommand.cpp" />
<ClCompile Include="tier0\completion.cpp" /> <ClCompile Include="tier0\completion.cpp" />
<ClCompile Include="tier0\cvar.cpp" /> <ClCompile Include="tier0\cvar.cpp" />
@ -119,6 +219,7 @@
<ClInclude Include="common\opcodes.h" /> <ClInclude Include="common\opcodes.h" />
<ClInclude Include="common\protocol.h" /> <ClInclude Include="common\protocol.h" />
<ClInclude Include="common\pseudodefs.h" /> <ClInclude Include="common\pseudodefs.h" />
<ClInclude Include="core\assert.h" />
<ClInclude Include="core\init.h" /> <ClInclude Include="core\init.h" />
<ClInclude Include="core\logdef.h" /> <ClInclude Include="core\logdef.h" />
<ClInclude Include="core\r5dev.h" /> <ClInclude Include="core\r5dev.h" />
@ -126,6 +227,7 @@
<ClInclude Include="ebisusdk\EbisuSDK.h" /> <ClInclude Include="ebisusdk\EbisuSDK.h" />
<ClInclude Include="engine\baseclient.h" /> <ClInclude Include="engine\baseclient.h" />
<ClInclude Include="engine\baseclientstate.h" /> <ClInclude Include="engine\baseclientstate.h" />
<ClInclude Include="engine\debugoverlay.h" />
<ClInclude Include="engine\host_cmd.h" /> <ClInclude Include="engine\host_cmd.h" />
<ClInclude Include="engine\host_state.h" /> <ClInclude Include="engine\host_state.h" />
<ClInclude Include="engine\net_chan.h" /> <ClInclude Include="engine\net_chan.h" />
@ -137,12 +239,15 @@
<ClInclude Include="inputsystem\ButtonCode.h" /> <ClInclude Include="inputsystem\ButtonCode.h" />
<ClInclude Include="inputsystem\inputsystem.h" /> <ClInclude Include="inputsystem\inputsystem.h" />
<ClInclude Include="launcher\IApplication.h" /> <ClInclude Include="launcher\IApplication.h" />
<ClInclude Include="materialsystem\materialsystem.h" />
<ClInclude Include="mathlib\adler32.h" /> <ClInclude Include="mathlib\adler32.h" />
<ClInclude Include="mathlib\bits.h" />
<ClInclude Include="mathlib\color.h" />
<ClInclude Include="mathlib\crc32.h" /> <ClInclude Include="mathlib\crc32.h" />
<ClInclude Include="mathlib\IceKey.H" /> <ClInclude Include="mathlib\IceKey.H" />
<ClInclude Include="mathlib\parallel_for.h" /> <ClInclude Include="mathlib\parallel_for.h" />
<ClInclude Include="mathlib\vector.h" /> <ClInclude Include="mathlib\vector.h" />
<ClInclude Include="networksystem\net_structs.h" /> <ClInclude Include="milessdk\win64_rrthreads.h" />
<ClInclude Include="networksystem\r5net.h" /> <ClInclude Include="networksystem\r5net.h" />
<ClInclude Include="networksystem\sm_protocol.h" /> <ClInclude Include="networksystem\sm_protocol.h" />
<ClInclude Include="public\include\memaddr.h" /> <ClInclude Include="public\include\memaddr.h" />
@ -160,6 +265,7 @@
<ClInclude Include="server\server.h" /> <ClInclude Include="server\server.h" />
<ClInclude Include="squirrel\sqapi.h" /> <ClInclude Include="squirrel\sqapi.h" />
<ClInclude Include="squirrel\sqinit.h" /> <ClInclude Include="squirrel\sqinit.h" />
<ClInclude Include="squirrel\sqnativefunctions.h" />
<ClInclude Include="squirrel\sqvm.h" /> <ClInclude Include="squirrel\sqvm.h" />
<ClInclude Include="thirdparty\detours\include\detours.h" /> <ClInclude Include="thirdparty\detours\include\detours.h" />
<ClInclude Include="thirdparty\detours\include\detver.h" /> <ClInclude Include="thirdparty\detours\include\detver.h" />
@ -176,7 +282,34 @@
<ClInclude Include="thirdparty\imgui\include\imstb_textedit.h" /> <ClInclude Include="thirdparty\imgui\include\imstb_textedit.h" />
<ClInclude Include="thirdparty\imgui\include\imstb_truetype.h" /> <ClInclude Include="thirdparty\imgui\include\imstb_truetype.h" />
<ClInclude Include="thirdparty\lzham\include\lzham.h" /> <ClInclude Include="thirdparty\lzham\include\lzham.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_assert.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_checksum.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_config.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_core.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_helpers.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_huffman_codes.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_lzbase.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_match_accel.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_math.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_mem.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_null_threading.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_platform.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_polar_codes.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_prefix_coding.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_pthreads_threading.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_static_lib.h" /> <ClInclude Include="thirdparty\lzham\include\lzham_static_lib.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_symbol_codec.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_threading.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_timer.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_traits.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_types.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_utils.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_vector.h" />
<ClInclude Include="thirdparty\lzham\include\lzham_win32_threading.h" />
<ClInclude Include="thirdparty\lzham\lzhamcomp\lzham_comp.h" />
<ClInclude Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp_internal.h" />
<ClInclude Include="thirdparty\lzham\lzhamdecomp\lzham_decomp.h" />
<ClInclude Include="thirdparty\lzham\lzhamdecomp\lzham_lzdecompbase.h" />
<ClInclude Include="thirdparty\spdlog\include\async.h" /> <ClInclude Include="thirdparty\spdlog\include\async.h" />
<ClInclude Include="thirdparty\spdlog\include\async_logger-inl.h" /> <ClInclude Include="thirdparty\spdlog\include\async_logger-inl.h" />
<ClInclude Include="thirdparty\spdlog\include\async_logger.h" /> <ClInclude Include="thirdparty\spdlog\include\async_logger.h" />
@ -272,6 +405,7 @@
<ClInclude Include="thirdparty\spdlog\include\tweakme.h" /> <ClInclude Include="thirdparty\spdlog\include\tweakme.h" />
<ClInclude Include="thirdparty\spdlog\include\version.h" /> <ClInclude Include="thirdparty\spdlog\include\version.h" />
<ClInclude Include="tier0\basetypes.h" /> <ClInclude Include="tier0\basetypes.h" />
<ClInclude Include="tier0\commandline.h" />
<ClInclude Include="tier0\ConCommand.h" /> <ClInclude Include="tier0\ConCommand.h" />
<ClInclude Include="tier0\completion.h" /> <ClInclude Include="tier0\completion.h" />
<ClInclude Include="tier0\cvar.h" /> <ClInclude Include="tier0\cvar.h" />
@ -368,7 +502,7 @@
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)r5dev\;$(IncludePath);$(DXSDK_DIR)Include</IncludePath> <IncludePath>$(SolutionDir)r5dev\;$(IncludePath);$(DXSDK_DIR)Include</IncludePath>
<LibraryPath>$(SolutionDir)r5dev\thirdparty\detours\libs;$(SolutionDir)r5dev\thirdparty\lzham\libs;$(LibraryPath);$(DXSDK_DIR)Lib\x64</LibraryPath> <LibraryPath>$(SolutionDir)r5dev\thirdparty\detours\libs;$(SolutionDir)r5dev\thirdparty\lzham\libs;$(LibraryPath);$(DXSDK_DIR)Lib\x64</LibraryPath>
<TargetName>r5apexvtxd</TargetName> <TargetName>r5apexsdkd</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir> <OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)build\$(ProjectName)\$(Configuration)\</IntDir> <IntDir>$(SolutionDir)build\$(ProjectName)\$(Configuration)\</IntDir>
<ReferencePath>$(VC_ReferencesPath_x64);</ReferencePath> <ReferencePath>$(VC_ReferencesPath_x64);</ReferencePath>
@ -436,10 +570,10 @@
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC> <EnableUAC>false</EnableUAC>
<ModuleDefinitionFile>r5dev.def</ModuleDefinitionFile> <ModuleDefinitionFile>r5dev.def</ModuleDefinitionFile>
<AdditionalDependencies>detours.lib;lzhamlib_x64D.lib;lzhamcomp_x64D.lib;lzhamdecomp_x64D.lib;d3d11.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>d3d11.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<PostBuildEvent> <PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "..\..\..\bin\$(TargetFileName)"</Command> <Command>copy /Y "$(TargetPath)" "..\..\..\$(TargetFileName)" &amp;&amp; del "..\..\..\r5apexsdkd64.dll" &amp;&amp; rename "..\..\..\$(TargetFileName)" "r5apexsdkd64.dll"</Command>
</PostBuildEvent> </PostBuildEvent>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -472,7 +606,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC> <EnableUAC>false</EnableUAC>
<ModuleDefinitionFile>r5dev.def</ModuleDefinitionFile> <ModuleDefinitionFile>r5dev.def</ModuleDefinitionFile>
<AdditionalDependencies>detours.lib;lzhamlib_x64.lib;lzhamcomp_x64.lib;lzhamdecomp_x64.lib;d3d11.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>d3d11.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<PostBuildEvent> <PostBuildEvent>
<Command>copy /Y "$(TargetPath)" "..\..\..\$(TargetFileName)" &amp;&amp; del "..\..\..\r5apexsdkd64.dll" &amp;&amp; rename "..\..\..\$(TargetFileName)" "r5apexsdkd64.dll"</Command> <Command>copy /Y "$(TargetPath)" "..\..\..\$(TargetFileName)" &amp;&amp; del "..\..\..\r5apexsdkd64.dll" &amp;&amp; rename "..\..\..\$(TargetFileName)" "r5apexsdkd64.dll"</Command>

View File

@ -121,6 +121,24 @@
<Filter Include="sdk\bsplib"> <Filter Include="sdk\bsplib">
<UniqueIdentifier>{336e3141-0276-4cd5-a836-585eef681b7b}</UniqueIdentifier> <UniqueIdentifier>{336e3141-0276-4cd5-a836-585eef681b7b}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="sdk\materialsystem">
<UniqueIdentifier>{55bb4f60-5f5a-4780-a7a2-b3db51c53680}</UniqueIdentifier>
</Filter>
<Filter Include="sdk\milessdk">
<UniqueIdentifier>{f52dfb17-f5bd-4258-91a2-500587bee708}</UniqueIdentifier>
</Filter>
<Filter Include="thirdparty\lzham\lzhamcomp">
<UniqueIdentifier>{f450ee50-7010-49e2-9f91-05a74fcb6a8b}</UniqueIdentifier>
</Filter>
<Filter Include="thirdparty\lzham\lzhamcomp\include">
<UniqueIdentifier>{11645361-fd70-462f-ab8b-8a78283a5fc7}</UniqueIdentifier>
</Filter>
<Filter Include="thirdparty\lzham\lzhamdecomp">
<UniqueIdentifier>{785353c2-6417-4213-b55f-3007a0b79801}</UniqueIdentifier>
</Filter>
<Filter Include="thirdparty\lzham\lzhamdecomp\include">
<UniqueIdentifier>{5beb12b5-0422-4337-9be6-2e6c0a05a69b}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="client\client.cpp"> <ClCompile Include="client\client.cpp">
@ -303,8 +321,89 @@
<ClCompile Include="windows\system.cpp"> <ClCompile Include="windows\system.cpp">
<Filter>windows</Filter> <Filter>windows</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="IDevPallete.cpp"> <ClCompile Include="thirdparty\detours\src\disasm.cpp">
<Filter>sdk\gameui</Filter> <Filter>thirdparty\detours</Filter>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\modules.cpp">
<Filter>thirdparty\detours</Filter>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\detours.cpp">
<Filter>thirdparty\detours</Filter>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\creatwth.cpp">
<Filter>thirdparty\detours</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_assert.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_checksum.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_huffman_codes.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_lzbase.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_match_accel.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_mem.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_platform.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_polar_codes.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_prefix_coding.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_pthreads_threading.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_symbol_codec.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_timer.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_vector.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_win32_threading.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzham_api.cpp">
<Filter>thirdparty\lzham</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp_internal.cpp">
<Filter>thirdparty\lzham\lzhamcomp</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp_state.cpp">
<Filter>thirdparty\lzham\lzhamcomp</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp.cpp">
<Filter>thirdparty\lzham\lzhamcomp</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamdecomp\lzham_lzdecomp.cpp">
<Filter>thirdparty\lzham\lzhamdecomp</Filter>
</ClCompile>
<ClCompile Include="thirdparty\lzham\lzhamdecomp\lzham_lzdecompbase.cpp">
<Filter>thirdparty\lzham\lzhamdecomp</Filter>
</ClCompile>
<ClCompile Include="mathlib\bits.cpp">
<Filter>sdk\mathlib</Filter>
</ClCompile>
<ClCompile Include="tier0\commandline.cpp">
<Filter>sdk\tier0</Filter>
</ClCompile>
<ClCompile Include="core\logdef.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="squirrel\sqnativefunctions.cpp">
<Filter>sdk\squirrel</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -815,12 +914,6 @@
<ClInclude Include="public\include\binstream.h"> <ClInclude Include="public\include\binstream.h">
<Filter>sdk\public\include</Filter> <Filter>sdk\public\include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_static_lib.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="mathlib\adler32.h"> <ClInclude Include="mathlib\adler32.h">
<Filter>sdk\mathlib</Filter> <Filter>sdk\mathlib</Filter>
</ClInclude> </ClInclude>
@ -839,11 +932,116 @@
<ClInclude Include="windows\system.h"> <ClInclude Include="windows\system.h">
<Filter>windows</Filter> <Filter>windows</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="networksystem\net_structs.h"> <ClInclude Include="mathlib\color.h">
<Filter>sdk\networksystem</Filter> <Filter>sdk\mathlib</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="IDevPalette.h"> <ClInclude Include="materialsystem\materialsystem.h">
<Filter>sdk\gameui</Filter> <Filter>sdk\materialsystem</Filter>
</ClInclude>
<ClInclude Include="engine\debugoverlay.h">
<Filter>sdk\engine</Filter>
</ClInclude>
<ClInclude Include="milessdk\win64_rrthreads.h">
<Filter>sdk\milessdk</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_config.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_core.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_helpers.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_huffman_codes.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_lzbase.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_match_accel.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_math.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_mem.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_null_threading.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_platform.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_polar_codes.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_prefix_coding.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_pthreads_threading.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_static_lib.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_symbol_codec.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_threading.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_timer.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_traits.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_types.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_utils.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_vector.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_win32_threading.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_assert.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\include\lzham_checksum.h">
<Filter>thirdparty\lzham\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\lzhamcomp\lzham_comp.h">
<Filter>thirdparty\lzham\lzhamcomp\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\lzhamcomp\lzham_lzcomp_internal.h">
<Filter>thirdparty\lzham\lzhamcomp\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\lzhamdecomp\lzham_decomp.h">
<Filter>thirdparty\lzham\lzhamdecomp\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\lzham\lzhamdecomp\lzham_lzdecompbase.h">
<Filter>thirdparty\lzham\lzhamdecomp\include</Filter>
</ClInclude>
<ClInclude Include="mathlib\bits.h">
<Filter>sdk\mathlib</Filter>
</ClInclude>
<ClInclude Include="tier0\commandline.h">
<Filter>sdk\tier0</Filter>
</ClInclude>
<ClInclude Include="core\assert.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="squirrel\sqnativefunctions.h">
<Filter>sdk\squirrel</Filter>
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -51,10 +51,10 @@ void HRtech_AsyncLoad(std::string svPakFileName)
void RTech_Game_Attach() void RTech_Game_Attach()
{ {
DetourAttach((LPVOID*)&RTech_UnloadAsset, &HRTech_UnloadAsset); //DetourAttach((LPVOID*)&RTech_UnloadAsset, &HRTech_UnloadAsset);
} }
void RTech_Game_Detach() void RTech_Game_Detach()
{ {
DetourAttach((LPVOID*)&RTech_UnloadAsset, &HRTech_UnloadAsset); //DetourAttach((LPVOID*)&RTech_UnloadAsset, &HRTech_UnloadAsset);
} }

View File

@ -7,12 +7,15 @@ namespace
ADDRESS p_RTech_UnloadAsset = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x28\x48\x85\xC9\x0F\x84\x00\x00\x00\x00\x48\x8B\x05\x00\x00\x00\x00", "xxxxxxxxx????xxx????"); ADDRESS p_RTech_UnloadAsset = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x28\x48\x85\xC9\x0F\x84\x00\x00\x00\x00\x48\x8B\x05\x00\x00\x00\x00", "xxxxxxxxx????xxx????");
void (*RTech_UnloadAsset)(std::int64_t a1) = (void (*)(std::int64_t))p_RTech_UnloadAsset.GetPtr(); /*48 83 EC 28 48 85 C9 0F 84 ? ? ? ? 48 8B 05 ? ? ? ? */ void (*RTech_UnloadAsset)(std::int64_t a1) = (void (*)(std::int64_t))p_RTech_UnloadAsset.GetPtr(); /*48 83 EC 28 48 85 C9 0F 84 ? ? ? ? 48 8B 05 ? ? ? ? */
ADDRESS p_RTech_AsyncLoad = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x40\x48\x89\x6C\x24\x00\x41\x8B\xE8", "xxxxxxxxxx?xxx");
unsigned int (*RTech_AsyncLoad)(void* Src, __int64 a2, int a3, char pakfile) = (unsigned int (*)(void*, __int64, int, char))p_RTech_AsyncLoad.GetPtr(); /*40 53 48 83 EC 40 48 89 6C 24 ? 41 8B E8*/
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3) #elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
ADDRESS p_RTech_UnloadAsset = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x28\x48\x85\xD2\x74\x40\x48\x8B\x05\x00\x00\x00\x00", "xxxxxxxxxxxx????"); ADDRESS p_RTech_UnloadAsset = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x28\x48\x85\xD2\x74\x40\x48\x8B\x05\x00\x00\x00\x00", "xxxxxxxxxxxx????");
void (*RTech_UnloadAsset)(std::int64_t a1, std::int64_t a2) = (void (*)(std::int64_t, std::int64_t))p_RTech_UnloadAsset.GetPtr(); /*48 83 EC 28 48 85 D2 74 40 48 8B 05 ? ? ? ?*/ void (*RTech_UnloadAsset)(std::int64_t a1, std::int64_t a2) = (void (*)(std::int64_t, std::int64_t))p_RTech_UnloadAsset.GetPtr(); /*48 83 EC 28 48 85 D2 74 40 48 8B 05 ? ? ? ?*/
#endif
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) || defined (GAMEDLL_S2)
ADDRESS p_RTech_AsyncLoad = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x40\x48\x89\x6C\x24\x00\x41\x8B\xE8", "xxxxxxxxxx?xxx");
unsigned int (*RTech_AsyncLoad)(void* Src, __int64 a2, int a3, char pakfile) = (unsigned int (*)(void*, __int64, int, char))p_RTech_AsyncLoad.GetPtr(); /*40 53 48 83 EC 40 48 89 6C 24 ? 41 8B E8*/
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
ADDRESS p_RTech_AsyncLoad = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x40\x48\x89\x6C\x24\x00\x41\x0F\xB6\xE9", "xxxxxxxxxx?xxxx"); ADDRESS p_RTech_AsyncLoad = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x40\x48\x89\x6C\x24\x00\x41\x0F\xB6\xE9", "xxxxxxxxxx?xxxx");
unsigned int (*RTech_AsyncLoad)(void* Src, __int64 a2, int a3, char pakfile) = (unsigned int (*)(void*, __int64, int, char))p_RTech_AsyncLoad.GetPtr(); /*40 53 48 83 EC 40 48 89 6C 24 ? 41 0F B6 E9*/ unsigned int (*RTech_AsyncLoad)(void* Src, __int64 a2, int a3, char pakfile) = (unsigned int (*)(void*, __int64, int, char))p_RTech_AsyncLoad.GetPtr(); /*40 53 48 83 EC 40 48 89 6C 24 ? 41 0F B6 E9*/
#endif #endif

View File

@ -140,7 +140,7 @@
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>detours.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<PostBuildEvent> <PostBuildEvent>
<Command>del "..\..\..\r5reloaded.exe" &amp;&amp; copy /Y "$(TargetPath)" "..\..\..\$(TargetFileName)"</Command> <Command>del "..\..\..\r5reloaded.exe" &amp;&amp; copy /Y "$(TargetPath)" "..\..\..\$(TargetFileName)"</Command>
@ -174,7 +174,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>detours.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<PostBuildEvent> <PostBuildEvent>
<Command>del "..\..\..\r5reloaded.exe" &amp;&amp; copy /Y "$(TargetPath)" "..\..\..\$(TargetFileName)"</Command> <Command>del "..\..\..\r5reloaded.exe" &amp;&amp; copy /Y "$(TargetPath)" "..\..\..\$(TargetFileName)"</Command>
@ -186,6 +186,22 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile> </ClCompile>
<ClCompile Include="sdklauncher\sdklauncher.cpp" /> <ClCompile Include="sdklauncher\sdklauncher.cpp" />
<ClCompile Include="thirdparty\detours\src\creatwth.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\detours.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\disasm.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\modules.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="resource\sdklauncher.rc" /> <ResourceCompile Include="resource\sdklauncher.rc" />
@ -198,6 +214,9 @@
<ClInclude Include="core\stdafx.h" /> <ClInclude Include="core\stdafx.h" />
<ClInclude Include="sdklauncher\sdklauncher.h" /> <ClInclude Include="sdklauncher\sdklauncher.h" />
<ClInclude Include="sdklauncher\sdklauncher_res.h" /> <ClInclude Include="sdklauncher\sdklauncher_res.h" />
<ClInclude Include="thirdparty\detours\include\detours.h" />
<ClInclude Include="thirdparty\detours\include\detver.h" />
<ClInclude Include="thirdparty\detours\include\syelog.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@ -13,6 +13,12 @@
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter> </Filter>
<Filter Include="Detours Files">
<UniqueIdentifier>{82b18787-373d-42ce-8d8d-1e3adba8d3a0}</UniqueIdentifier>
</Filter>
<Filter Include="Detours Files\include">
<UniqueIdentifier>{dc968871-7ca2-452b-a5b1-350a12dd54aa}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="sdklauncher\sdklauncher.cpp"> <ClCompile Include="sdklauncher\sdklauncher.cpp">
@ -21,6 +27,18 @@
<ClCompile Include="core\stdafx.cpp"> <ClCompile Include="core\stdafx.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="thirdparty\detours\src\detours.cpp">
<Filter>Detours Files</Filter>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\disasm.cpp">
<Filter>Detours Files</Filter>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\modules.cpp">
<Filter>Detours Files</Filter>
</ClCompile>
<ClCompile Include="thirdparty\detours\src\creatwth.cpp">
<Filter>Detours Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="resource\sdklauncher.rc"> <ResourceCompile Include="resource\sdklauncher.rc">
@ -37,6 +55,15 @@
<ClInclude Include="sdklauncher\sdklauncher_res.h"> <ClInclude Include="sdklauncher\sdklauncher_res.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="thirdparty\detours\include\detver.h">
<Filter>Detours Files\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\detours\include\syelog.h">
<Filter>Detours Files\include</Filter>
</ClInclude>
<ClInclude Include="thirdparty\detours\include\detours.h">
<Filter>Detours Files\include</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Image Include="resource\ico\sdklauncher_rel.ico"> <Image Include="resource\ico\sdklauncher_rel.ico">

View File

@ -56,7 +56,7 @@ bool LaunchR5Apex(LAUNCHMODE lMode, LAUNCHSTATE lState)
} }
cfgFile.close(); // Close cfg file. cfgFile.close(); // Close cfg file.
WorkerDll = currentDirectory + "\\bin\\r5apexvtxd.dll"; // Get path to worker dll. WorkerDll = currentDirectory + "\\r5apexsdkd64.dll"; // Get path to worker dll.
GameDirectory = currentDirectory + "\\r5apex.exe"; // Get path to game executeable. GameDirectory = currentDirectory + "\\r5apex.exe"; // Get path to game executeable.
StartupCommandLine = currentDirectory + "\\r5apex.exe " + CommandLineArguments; // Setup startup command line string. StartupCommandLine = currentDirectory + "\\r5apex.exe " + CommandLineArguments; // Setup startup command line string.

View File

@ -18,7 +18,7 @@ bool HIVEngineServer_PersistenceAvailable(void* entidx, int clientidx)
CClient* pClient = g_pClient->GetClientInstance(clientidx); // Get client instance. CClient* pClient = g_pClient->GetClientInstance(clientidx); // Get client instance.
*(char*)((std::uintptr_t)pClient + g_dwPersistenceVar) = (char)0x5; // Set the client instance to 'ready'. *(char*)((std::uintptr_t)pClient + g_dwPersistenceVar) = (char)0x5; // Set the client instance to 'ready'.
if (!g_bIsPersistenceVarSet[clientidx] && sv_showconnecting->m_pParent->m_iValue > 0) if (!g_bIsPersistenceVarSet[clientidx] && sv_showconnecting->GetBool())
{ {
void* clientNamePtr = (void**)(((std::uintptr_t)pClient->GetNetChan()) + 0x1A8D); // Get client name from netchan. void* clientNamePtr = (void**)(((std::uintptr_t)pClient->GetNetChan()) + 0x1A8D); // Get client name from netchan.
std::string clientName((char*)clientNamePtr, 32); // Get full name. std::string clientName((char*)clientNamePtr, 32); // Get full name.
@ -66,4 +66,4 @@ void IVEngineServer_Detach()
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
bool g_bIsPersistenceVarSet[128]; bool g_bIsPersistenceVarSet[MAX_PLAYERS];

View File

@ -14,7 +14,7 @@ void IVEngineServer_Attach();
void IVEngineServer_Detach(); void IVEngineServer_Detach();
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
extern bool g_bIsPersistenceVarSet[128]; extern bool g_bIsPersistenceVarSet[MAX_PLAYERS];
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class HVEngineServer : public IDetour class HVEngineServer : public IDetour

View File

@ -24,33 +24,13 @@ void IsClientBanned(R5Net::Client* pR5net, const std::string svIPAddr, std::int6
bool bCompBanned = res.isBanned; bool bCompBanned = res.isBanned;
if (bCompBanned) if (bCompBanned)
{ {
while (bCompBanned) DevMsg(eDLL_T::SERVER, "\n");
{ DevMsg(eDLL_T::SERVER, "______________________________________________________________\n");
std::this_thread::sleep_for(std::chrono::milliseconds(500)); DevMsg(eDLL_T::SERVER, "] PYLON NOTICE -----------------------------------------------\n");
for (int i = 0; i < MAX_PLAYERS; i++) // Loop through all possible client instances. DevMsg(eDLL_T::SERVER, "] OriginID : | '%lld' IS PYLON BANNED.\n", nNucleusID);
{ DevMsg(eDLL_T::SERVER, "--------------------------------------------------------------\n");
CClient* pClient = g_pClient->GetClientInstance(i); // Get client instance. DevMsg(eDLL_T::SERVER, "\n");
if (!pClient) // Client instance valid? g_pBanSystem->AddConnectionRefuse(svError, nNucleusID); // Add to the vector.
{
continue;
}
if (!pClient->GetNetChan()) // Netchan valid?
{
continue;
}
std::int64_t nOriginID = pClient->m_iOriginID; // Get originID.
if (nOriginID != nNucleusID) // See if they match.
{
continue;
}
g_pBanSystem->AddConnectionRefuse(svError, pClient->m_iUserID + 1); // Add to the vector.
bCompBanned = false;
break;
}
}
} }
} }
@ -73,7 +53,7 @@ void* HCServer_Authenticate(void* pServer, user_creds* pInpacket)
svIpAddress = ss.str(); svIpAddress = ss.str();
} }
if (sv_showconnecting->m_pParent->m_iValue > 0) if (sv_showconnecting->GetBool())
{ {
DevMsg(eDLL_T::SERVER, "\n"); DevMsg(eDLL_T::SERVER, "\n");
DevMsg(eDLL_T::SERVER, "______________________________________________________________\n"); DevMsg(eDLL_T::SERVER, "______________________________________________________________\n");
@ -90,7 +70,7 @@ void* HCServer_Authenticate(void* pServer, user_creds* pInpacket)
{ {
CServer_RejectConnection(pServer, *(unsigned int*)((std::uintptr_t)pServer + 0xC), pInpacket, "You have been banned from this Server."); // RejectConnection for the client. CServer_RejectConnection(pServer, *(unsigned int*)((std::uintptr_t)pServer + 0xC), pInpacket, "You have been banned from this Server."); // RejectConnection for the client.
if (sv_showconnecting->m_pParent->m_iValue > 0) if (sv_showconnecting->GetBool())
{ {
DevMsg(eDLL_T::SERVER, "] NOTICE : | THIS CLIENT IS BANNED!\n"); DevMsg(eDLL_T::SERVER, "] NOTICE : | THIS CLIENT IS BANNED!\n");
DevMsg(eDLL_T::SERVER, "--------------------------------------------------------------\n\n"); DevMsg(eDLL_T::SERVER, "--------------------------------------------------------------\n\n");
@ -98,7 +78,7 @@ void* HCServer_Authenticate(void* pServer, user_creds* pInpacket)
return nullptr; return nullptr;
} }
} }
if (sv_showconnecting->m_pParent->m_iValue > 0) if (sv_showconnecting->GetBool())
{ {
DevMsg(eDLL_T::SERVER, "\n"); DevMsg(eDLL_T::SERVER, "\n");
} }

View File

@ -16,6 +16,8 @@ struct user_creds
namespace namespace
{ {
/* ==== CSERVER ========================================================================================================================================================= */ /* ==== CSERVER ========================================================================================================================================================= */
ADDRESS p_CServer_Think = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x74\x24\x00\x57\x48\x81\xEC\x00\x00\x00\x00\x80\x3D\x00\x00\x00\x00\x00", "xxxx?xxxx?xxxx????xx?????");
void (*CServer_Think)(bool check_clock_drift, bool bIsSimulating) = (void (*)(bool, bool))p_CServer_Think.GetPtr(); /*48 89 5C 24 ? 48 89 74 24 ? 57 48 81 EC ? ? ? ? 80 3D ? ? ? ? ?*/
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) #if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
ADDRESS p_CServer_Authenticate = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x44\x89\x44\x24\x00\x55\x56\x57\x48\x8D\xAC\x24\x00\x00\x00\x00", "xxxx?xxxxxxx????"); ADDRESS p_CServer_Authenticate = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x44\x89\x44\x24\x00\x55\x56\x57\x48\x8D\xAC\x24\x00\x00\x00\x00", "xxxx?xxxxxxx????");
void* (*CServer_Authenticate)(void* cserver, user_creds* creds) = (void* (*)(void* cserver, user_creds * creds))p_CServer_Authenticate.GetPtr(); /*44 89 44 24 ?? 55 56 57 48 8D AC 24 ?? ?? ?? ??*/ void* (*CServer_Authenticate)(void* cserver, user_creds* creds) = (void* (*)(void* cserver, user_creds * creds))p_CServer_Authenticate.GetPtr(); /*44 89 44 24 ?? 55 56 57 48 8D AC 24 ?? ?? ?? ??*/
@ -28,6 +30,8 @@ namespace
#endif #endif
ADDRESS p_CServer_RejectConnection = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x4C\x89\x4C\x24\x00\x53\x55\x56\x57\x48\x81\xEC\x00\x00\x00\x00\x49\x8B\xD9", "xxxx?xxxxxxx????xxx"); ADDRESS p_CServer_RejectConnection = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x4C\x89\x4C\x24\x00\x53\x55\x56\x57\x48\x81\xEC\x00\x00\x00\x00\x49\x8B\xD9", "xxxx?xxxxxxx????xxx");
void* (*CServer_RejectConnection)(void* pServer, unsigned int a2, user_creds* pCreds, const char* szMessage) = (void* (*)(void*, unsigned int, user_creds*, const char*))p_CServer_RejectConnection.GetPtr(); /*4C 89 4C 24 ?? 53 55 56 57 48 81 EC ?? ?? ?? ?? 49 8B D9*/ void* (*CServer_RejectConnection)(void* pServer, unsigned int a2, user_creds* pCreds, const char* szMessage) = (void* (*)(void*, unsigned int, user_creds*, const char*))p_CServer_RejectConnection.GetPtr(); /*4C 89 4C 24 ?? 53 55 56 57 48 81 EC ?? ?? ?? ?? 49 8B D9*/
int* sv_m_nTickCount = p_CServer_Think.Offset(0xB0).FindPatternSelf("8B 15", ADDRESS::Direction::DOWN).ResolveRelativeAddressSelf(0x2, 0x6).RCast<int*>();
} }
void CServer_Attach(); void CServer_Attach();
@ -42,8 +46,10 @@ class HServer : public IDetour
{ {
virtual void debugp() virtual void debugp()
{ {
std::cout << "| FUN: CServer::Think : 0x" << std::hex << std::uppercase << p_CServer_Think.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: CServer::Authenticate : 0x" << std::hex << std::uppercase << p_CServer_Authenticate.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: CServer::Authenticate : 0x" << std::hex << std::uppercase << p_CServer_Authenticate.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| FUN: CServer::RejectConnection : 0x" << std::hex << std::uppercase << p_CServer_RejectConnection.GetPtr() << std::setw(npad) << " |" << std::endl; std::cout << "| FUN: CServer::RejectConnection : 0x" << std::hex << std::uppercase << p_CServer_RejectConnection.GetPtr() << std::setw(npad) << " |" << std::endl;
std::cout << "| VAR: sv_m_nTickCount : 0x" << std::hex << std::uppercase << sv_m_nTickCount << std::setw(0) << " |" << std::endl;
std::cout << "+----------------------------------------------------------------+" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl;
} }
}; };

View File

@ -48,6 +48,12 @@ void hsq_newslot(void* sqvm, int idx);
void SQAPI_Attach(); void SQAPI_Attach();
void SQAPI_Detach(); void SQAPI_Detach();
typedef int SQRESULT;
#define SQ_OK (1)
#define SQ_ERROR (-1)
#define SQ_FAILED(res) (res<0)
#define SQ_SUCCEEDED(res) (res>=0)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class HSqapi : public IDetour class HSqapi : public IDetour
{ {

View File

@ -0,0 +1,265 @@
#include "core/stdafx.h"
#include "squirrel/sqnativefunctions.h"
#include "engine/sys_utils.h"
#include "gameui/IBrowser.h"
namespace SQNativeFunctions
{
namespace IBrowser
{
//----------------------------------------------------------------------------
// Purpose: get servers current server name from serverlist index
//-----------------------------------------------------------------------------
SQRESULT GetServerName(void* sqvm)
{
int svIndex = hsq_getinteger(sqvm, 1);
std::string szSvName = g_pIBrowser->m_vServerList[svIndex].svServerName;
hsq_pushstring(sqvm, szSvName.c_str(), -1);
return SQ_OK;
}
//----------------------------------------------------------------------------
// Purpose: get servers current playlist via serverlist index
//-----------------------------------------------------------------------------
SQRESULT GetServerPlaylist(void* sqvm)
{
int svIndex = hsq_getinteger(sqvm, 1);
std::string szSvPlaylist = g_pIBrowser->m_vServerList[svIndex].svPlaylist;
hsq_pushstring(sqvm, szSvPlaylist.c_str(), -1);
return SQ_OK;
}
//----------------------------------------------------------------------------
// Purpose: get servers current map via serverlist index
//-----------------------------------------------------------------------------
SQRESULT GetServerMap(void* sqvm)
{
int svIndex = hsq_getinteger(sqvm, 1);
std::string szSvMapName = g_pIBrowser->m_vServerList[svIndex].svMapName;
hsq_pushstring(sqvm, szSvMapName.c_str(), -1);
return SQ_OK;
}
//----------------------------------------------------------------------------
// Purpose: get current server count from pylon
//-----------------------------------------------------------------------------
SQRESULT GetServerCount(void* sqvm)
{
g_pIBrowser->GetServerList(); // Refresh svListing list.
hsq_pushinteger(sqvm, g_pIBrowser->m_vServerList.size());
return SQ_OK;
}
//----------------------------------------------------------------------------
// Purpose: expose SDK version to SQ
//-----------------------------------------------------------------------------
SQRESULT GetSDKVersion(void* sqvm)
{
hsq_pushstring(sqvm, g_pR5net->GetSDKVersion().c_str(), -1);
return SQ_OK;
}
//----------------------------------------------------------------------------
// Purpose: get promo data for serverbrowser panels
//-----------------------------------------------------------------------------
SQRESULT GetPromoData(void* sqvm)
{
enum class R5RPromoData : int
{
PromoLargeTitle,
PromoLargeDesc,
PromoLeftTitle,
PromoLeftDesc,
PromoRightTitle,
PromoRightDesc
};
R5RPromoData ePromoIndex = (R5RPromoData)hsq_getinteger(sqvm, 1);
std::string szPromo = std::string();
switch (ePromoIndex)
{
case R5RPromoData::PromoLargeTitle:
{
szPromo = "Welcome To R5Reloaded!";
break;
}
case R5RPromoData::PromoLargeDesc:
{
szPromo = "Make sure to join the discord! discord.gg/r5reloaded";
break;
}
case R5RPromoData::PromoLeftTitle:
{
szPromo = "Yes";
break;
}
case R5RPromoData::PromoLeftDesc:
{
szPromo = "Your ad could be here";
break;
}
case R5RPromoData::PromoRightTitle:
{
szPromo = "Yes2";
break;
}
case R5RPromoData::PromoRightDesc:
{
szPromo = "Yes3";
break;
}
default:
{
szPromo = "You should not see this.";
break;
}
}
hsq_pushstring(sqvm, szPromo.c_str(), -1);
return SQ_OK;
}
//-----------------------------------------------------------------------------
// Purpose: set netchannel encryption key and connect to server
//-----------------------------------------------------------------------------
SQRESULT SetEncKeyAndConnect(void* sqvm)
{
int svIndex = hsq_getinteger(sqvm, 1);
g_pIBrowser->ConnectToServer(g_pIBrowser->m_vServerList[svIndex].svIpAddress, g_pIBrowser->m_vServerList[svIndex].svPort, g_pIBrowser->m_vServerList[svIndex].svEncryptionKey);
return SQ_OK;
}
//-----------------------------------------------------------------------------
// Purpose: create server via native serverbrowser entries
//-----------------------------------------------------------------------------
SQRESULT CreateServerFromMenu(void* sqvm)
{
std::string szSvName = hsq_getstring(sqvm, 1);
std::string szSvMapName = hsq_getstring(sqvm, 2);
std::string szSvPlaylist = hsq_getstring(sqvm, 3);
EServerVisibility eSvVisibility = (EServerVisibility)hsq_getinteger(sqvm, 4);
if (szSvName.empty() || szSvMapName.empty() || szSvPlaylist.empty())
return SQ_OK;
// Adjust browser settings.
g_pIBrowser->m_Server.svPlaylist = szSvPlaylist;
g_pIBrowser->m_Server.svMapName = szSvMapName;
g_pIBrowser->m_Server.svServerName = szSvName;
g_pIBrowser->eServerVisibility = eSvVisibility;
// Launch server.
g_pIBrowser->LaunchServer();
return SQ_OK;
}
//-----------------------------------------------------------------------------
// // Purpose: request token from pylon and join server with result.
//-----------------------------------------------------------------------------
SQRESULT JoinPrivateServerFromMenu(void* sqvm)
{
std::string szHiddenServerRequestMessage = std::string();
std::string szToken = hsq_getstring(sqvm, 1);
ServerListing svListing;
bool result = g_pR5net->GetServerByToken(svListing, szHiddenServerRequestMessage, szToken); // Send szToken connect request.
if (result)
{
g_pIBrowser->ConnectToServer(svListing.svIpAddress, svListing.svPort, svListing.svEncryptionKey);
}
return SQ_OK;
}
//-----------------------------------------------------------------------------
// Purpose: get response from private server request
//-----------------------------------------------------------------------------
SQRESULT GetPrivateServerMessage(void* sqvm)
{
std::string szHiddenServerRequestMessage = std::string();
std::string szToken = hsq_getstring(sqvm, 1);
ServerListing slServer;
bool result = g_pR5net->GetServerByToken(slServer, szHiddenServerRequestMessage, szToken); // Send szToken connect request.
if (!slServer.svServerName.empty())
{
szHiddenServerRequestMessage = "Found Server: " + slServer.svServerName;
hsq_pushstring(sqvm, szHiddenServerRequestMessage.c_str(), -1);
}
else
{
szHiddenServerRequestMessage = "Error: Server Not Found";
hsq_pushstring(sqvm, szHiddenServerRequestMessage.c_str(), -1);
}
DevMsg(eDLL_T::UI, "GetPrivateServeMessage response: %s\n", szHiddenServerRequestMessage.c_str());
return SQ_OK;
}
//-----------------------------------------------------------------------------
// Purpose: connect to server from native server browser entries
//-----------------------------------------------------------------------------
SQRESULT ConnectToIPFromMenu(void* sqvm)
{
std::string szIP = hsq_getstring(sqvm, 1);
std::string szEncKey = hsq_getstring(sqvm, 2);
if (szIP.empty() || szEncKey.empty())
return SQ_OK;
DevMsg(eDLL_T::UI, "Connecting to server with connection string %s and encryptionkey %s\n", szIP, szEncKey);
g_pIBrowser->ConnectToServer(szIP, szEncKey);
return SQ_OK;
}
//-----------------------------------------------------------------------------
// Purpose: return all available map
//-----------------------------------------------------------------------------
SQRESULT GetAvailableMaps(void* sqvm)
{
std::vector<std::string> mapList = g_pIBrowser->m_vszMapFileNameList;
if (mapList.empty())
{
DevMsg(eDLL_T::UI, "Available maps is empty!!!\n");
return SQ_OK;
}
DevMsg(eDLL_T::UI, "Requesting an array of %i available maps from script\n", mapList.size());
hsq_newarray(sqvm, 0);
for (auto& it : mapList)
{
hsq_pushstring(sqvm, it.c_str(), -1);
hsq_arrayappend(sqvm, -2);
}
return SQ_OK;
}
}
}

View File

@ -0,0 +1,21 @@
#pragma once
#include "squirrel/sqapi.h"
namespace SQNativeFunctions
{
namespace IBrowser
{
SQRESULT GetServerName(void* sqvm);
SQRESULT GetServerPlaylist(void* sqvm);
SQRESULT GetServerMap(void* sqvm);
SQRESULT GetServerCount(void* sqvm);
SQRESULT GetSDKVersion(void* sqvm);
SQRESULT GetPromoData(void* sqvm);
SQRESULT SetEncKeyAndConnect(void* sqvm);
SQRESULT CreateServerFromMenu(void* sqvm);
SQRESULT JoinPrivateServerFromMenu(void* sqvm);
SQRESULT GetPrivateServerMessage(void* sqvm);
SQRESULT ConnectToIPFromMenu(void* sqvm);
SQRESULT GetAvailableMaps(void* sqvm);
}
}

View File

@ -9,11 +9,12 @@
#include "tier0/basetypes.h" #include "tier0/basetypes.h"
#include "tier0/cvar.h" #include "tier0/cvar.h"
#include "tier0/IConVar.h" #include "tier0/IConVar.h"
#include "tier0/commandline.h"
#include "engine/sys_utils.h" #include "engine/sys_utils.h"
#include "squirrel/sqvm.h"
#include "vgui/CEngineVGui.h" #include "vgui/CEngineVGui.h"
#include "gameui/IConsole.h" #include "gameui/IConsole.h"
#include "serverbrowser/serverbrowser.h" #include "squirrel/sqvm.h"
#include "squirrel/sqnativefunctions.h"
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// Purpose: prints the output of each VM to the console // Purpose: prints the output of each VM to the console
@ -22,66 +23,60 @@ void* HSQVM_PrintFunc(void* sqvm, char* fmt, ...)
{ {
#ifdef GAMEDLL_S3 #ifdef GAMEDLL_S3
int vmIdx = *(int*)((std::uintptr_t)sqvm + 0x18); int vmIdx = *(int*)((std::uintptr_t)sqvm + 0x18);
#else // TODO [ AMOS ]: nothing equal to 'rdx + 18h' exist in the vm pointers for anything below S3. #else // TODO [ AMOS ]: nothing equal to 'rdx + 18h' exist in the vm structs for anything below S3.
int vmIdx = 3; static int vmIdx = 3;
#endif #endif
static bool initialized = false; static char buf[1024] = {};
static char buf[1024]; static std::shared_ptr<spdlog::logger> iconsole = spdlog::get("game_console");
static std::string vmType[4] = { "Script(S):", "Script(C):", "Script(U):", "Script(X):" }; static std::shared_ptr<spdlog::logger> wconsole = spdlog::get("win_console");
static std::shared_ptr<spdlog::logger> sqlogger = spdlog::get("sqvm_print_logger");
static auto iconsole = spdlog::stdout_logger_mt("sqvm_print_iconsole"); // in-game console. {/////////////////////////////
static auto wconsole = spdlog::stdout_logger_mt("sqvm_print_wconsole"); // windows console. va_list args{};
static auto sqlogger = spdlog::basic_logger_mt("sqvm_print_logger", "platform\\logs\\sqvm_print.log"); // file logger.
std::string vmStr = vmType[vmIdx].c_str();
g_spd_sqvm_p_oss.str("");
g_spd_sqvm_p_oss.clear();
if (!initialized)
{
iconsole = std::make_shared<spdlog::logger>("sqvm_print_ostream", g_spd_sqvm_p_ostream_sink);
iconsole->set_pattern("[%S.%e] %v");
iconsole->set_level(spdlog::level::debug);
wconsole->set_pattern("[%S.%e] %v");
wconsole->set_level(spdlog::level::debug);
sqlogger->set_pattern("[%S.%e] %v");
sqlogger->set_level(spdlog::level::debug);
initialized = true;
}
va_list args;
va_start(args, fmt); va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args); vsnprintf(buf, sizeof(buf), fmt, args);
buf[sizeof(buf) - 1] = 0; buf[sizeof(buf) - 1] = 0;
va_end(args); va_end(args);
}/////////////////////////////
std::string vmStr = SQVM_LOG_T[vmIdx].c_str();
vmStr.append(buf); vmStr.append(buf);
if (sq_showvmoutput->m_pParent->m_iValue > 0) if (sq_showvmoutput->GetInt() > 0)
{ {
sqlogger->debug(vmStr); sqlogger->debug(vmStr);
} }
if (sq_showvmoutput->m_pParent->m_iValue > 1) if (sq_showvmoutput->GetInt() > 1)
{
if (!g_bSpdLog_UseAnsiClr)
{ {
iconsole->debug(vmStr);
wconsole->debug(vmStr); wconsole->debug(vmStr);
#ifndef DEDICATED
std::string s = g_spd_sqvm_p_oss.str();
const char* c = s.c_str();
Items.push_back(Strdup((const char*)c));
#endif // !DEDICATED
} }
#ifndef DEDICATED else
if (sq_showvmoutput->m_pParent->m_iValue > 2) {
std::string vmStrAnsi = SQVM_ANSI_LOG_T[vmIdx].c_str();
vmStrAnsi.append(buf);
wconsole->debug(vmStrAnsi);
}
#ifndef DEDICATED
g_spd_sys_w_oss.str("");
g_spd_sys_w_oss.clear();
iconsole->debug(vmStr);
std::string s = g_spd_sys_w_oss.str();
g_pIConsole->m_ivConLog.push_back(Strdup(s.c_str()));
if (sq_showvmoutput->GetInt() > 2)
{ {
std::string s = g_spd_sqvm_p_oss.str();
g_pLogSystem.AddLog((LogType_t)vmIdx, s); g_pLogSystem.AddLog((LogType_t)vmIdx, s);
} }
#endif // !DEDICATED #endif // !DEDICATED
}
return NULL; return NULL;
} }
@ -91,82 +86,63 @@ void* HSQVM_PrintFunc(void* sqvm, char* fmt, ...)
void* HSQVM_WarningFunc(void* sqvm, int a2, int a3, int* nStringSize, void** ppString) void* HSQVM_WarningFunc(void* sqvm, int a2, int a3, int* nStringSize, void** ppString)
{ {
void* result = SQVM_WarningFunc(sqvm, a2, a3, nStringSize, ppString); void* result = SQVM_WarningFunc(sqvm, a2, a3, nStringSize, ppString);
if (g_bSQVM_WarnFuncCalled) // Check if its SQVM_Warning calling. void* retaddr = _ReturnAddress();
if (retaddr != SQVM_WarningFunc) // Check if its SQVM_Warning calling.
{ {
return result; // If not return. return result; // If not return.
} }
static bool initialized = false;
static std::string vmType[4] = { "Script(S): WARNING: ", "Script(C): WARNING: ", "Script(U): WARNING: ", "Script(X): WARNING: " };
static auto iconsole = spdlog::stdout_logger_mt("sqvm_warn_iconsole"); // in-game console.
static auto wconsole = spdlog::stdout_logger_mt("sqvm_warn_wconsole"); // windows console.
static auto sqlogger = spdlog::basic_logger_mt("sqvm_warn_logger", "platform\\logs\\sqvm_warn.log"); // file logger.
#ifdef GAMEDLL_S3 #ifdef GAMEDLL_S3
int vmIdx = *(int*)((std::uintptr_t)sqvm + 0x18); int vmIdx = *(int*)((std::uintptr_t)sqvm + 0x18);
#else // TODO [ AMOS ]: nothing equal to 'rdx + 18h' exist in the vm pointers for anything below S3. #else // TODO [ AMOS ]: nothing equal to 'rdx + 18h' exist in the vm structs for anything below S3.
int vmIdx = 3; int vmIdx = 3;
#endif #endif
std::string vmStr = vmType[vmIdx].c_str();
g_spd_sqvm_w_oss.str(""); static std::shared_ptr<spdlog::logger> iconsole = spdlog::get("game_console");
g_spd_sqvm_w_oss.clear(); static std::shared_ptr<spdlog::logger> wconsole = spdlog::get("win_console");
static std::shared_ptr<spdlog::logger> sqlogger = spdlog::get("sqvm_warn_logger");
if (!initialized) std::string vmStr = SQVM_LOG_T[vmIdx].c_str();
{ std::string svConstructor((char*)*ppString, *nStringSize); // Get string from memory via std::string constructor.
iconsole = std::make_shared<spdlog::logger>("sqvm_warn_ostream", g_spd_sqvm_p_ostream_sink); vmStr.append(svConstructor);
iconsole->set_pattern("[%S.%e] %v\n");
iconsole->set_level(spdlog::level::debug);
wconsole->set_pattern("[%S.%e] %v\n");
wconsole->set_level(spdlog::level::debug);
sqlogger->set_pattern("[%S.%e] %v\n");
sqlogger->set_level(spdlog::level::debug);
initialized = true;
}
std::string stringConstructor((char*)*ppString, *nStringSize); // Get string from memory via std::string constructor. if (sq_showvmwarning->GetInt() > 0)
vmStr.append(stringConstructor);
std::string s = g_spd_sqvm_w_oss.str();
const char* c = s.c_str();
if (sq_showvmwarning->m_pParent->m_iValue > 0)
{ {
sqlogger->debug(vmStr); // Emit to file. sqlogger->debug(vmStr); // Emit to file.
} }
if (sq_showvmwarning->m_pParent->m_iValue > 1) if (sq_showvmwarning->GetInt() > 1)
{ {
iconsole->debug(vmStr); // Emit to in-game console. if (!g_bSpdLog_UseAnsiClr)
wconsole->debug(vmStr); // Emit to windows console. {
#ifndef DEDICATED wconsole->debug(vmStr);
std::string s = g_spd_sqvm_w_oss.str();
const char* c = s.c_str();
Items.push_back(Strdup(c));
#endif // !DEDICATED
} }
else
{
std::string vmStrAnsi = SQVM_ANSI_LOG_T[vmIdx].c_str();
vmStrAnsi.append(svConstructor);
wconsole->debug(vmStrAnsi);
}
#ifndef DEDICATED #ifndef DEDICATED
if (sq_showvmwarning->m_pParent->m_iValue > 2) g_spd_sys_w_oss.str("");
g_spd_sys_w_oss.clear();
iconsole->debug(vmStr); // Emit to in-game console.
std::string s = g_spd_sys_w_oss.str();
g_pIConsole->m_ivConLog.push_back(Strdup(s.c_str()));
if (sq_showvmwarning->GetInt() > 2)
{ {
g_pLogSystem.AddLog((LogType_t)vmIdx, s); g_pLogSystem.AddLog((LogType_t)vmIdx, s);
const char* c = s.c_str(); g_pIConsole->m_ivConLog.push_back(Strdup(s.c_str()));
Items.push_back(Strdup(c));
} }
#endif // !DEDICATED #endif // !DEDICATED
g_bSQVM_WarnFuncCalled = false; }
return result; return result;
} }
//---------------------------------------------------------------------------------
// Purpose:
//---------------------------------------------------------------------------------
void* HSQVM_WarningCmd(int a1, int a2)
{
g_bSQVM_WarnFuncCalled = true;
return SQVM_WarningCmd(a1, a2);
}
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
// Purpose: loads the include file from the mods directory // Purpose: loads the include file from the mods directory
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
@ -187,7 +163,7 @@ void* HSQVM_LoadRson(const char* szRsonName)
// Returns the new path if the rson exists on the disk // Returns the new path if the rson exists on the disk
if (FileExists(szFilePath) && SQVM_LoadRson(szRsonName)) if (FileExists(szFilePath) && SQVM_LoadRson(szRsonName))
{ {
if (sq_showrsonloading->m_pParent->m_iValue > 0) if (sq_showrsonloading->GetBool())
{ {
DevMsg(eDLL_T::ENGINE, "\n"); DevMsg(eDLL_T::ENGINE, "\n");
DevMsg(eDLL_T::ENGINE, "______________________________________________________________\n"); DevMsg(eDLL_T::ENGINE, "______________________________________________________________\n");
@ -200,7 +176,7 @@ void* HSQVM_LoadRson(const char* szRsonName)
} }
else else
{ {
if (sq_showrsonloading->m_pParent->m_iValue > 0) if (sq_showrsonloading->GetBool())
{ {
DevMsg(eDLL_T::ENGINE, "\n"); DevMsg(eDLL_T::ENGINE, "\n");
DevMsg(eDLL_T::ENGINE, "______________________________________________________________\n"); DevMsg(eDLL_T::ENGINE, "______________________________________________________________\n");
@ -230,7 +206,7 @@ bool HSQVM_LoadScript(void* sqvm, const char* szScriptPath, const char* szScript
} }
} }
if (sq_showscriptloading->m_pParent->m_iValue > 0) if (sq_showscriptloading->GetBool())
{ {
DevMsg(eDLL_T::ENGINE, "Loading SQVM Script '%s'\n", filepath); DevMsg(eDLL_T::ENGINE, "Loading SQVM Script '%s'\n", filepath);
} }
@ -241,7 +217,7 @@ bool HSQVM_LoadScript(void* sqvm, const char* szScriptPath, const char* szScript
return true; return true;
} }
if (sq_showscriptloading->m_pParent->m_iValue > 0) if (sq_showscriptloading->GetBool())
{ {
DevMsg(eDLL_T::ENGINE, "FAILED. Try SP / VPK for '%s'\n", filepath); DevMsg(eDLL_T::ENGINE, "FAILED. Try SP / VPK for '%s'\n", filepath);
} }
@ -272,7 +248,28 @@ int HSQVM_NativeTest(void* sqvm)
void RegisterUIScriptFunctions(void* sqvm) void RegisterUIScriptFunctions(void* sqvm)
{ {
HSQVM_RegisterFunction(sqvm, "UINativeTest", "native ui function", "void", "", &HSQVM_NativeTest); #ifndef DEDICATED
HSQVM_RegisterFunction(sqvm, "UINativeTest", "native ui test function", "void", "", &HSQVM_NativeTest);
// functions for retrieving server browser data
HSQVM_RegisterFunction(sqvm, "GetServerName", "get name of the server at the specified index of the server list", "string", "int", &SQNativeFunctions::IBrowser::GetServerName);
HSQVM_RegisterFunction(sqvm, "GetServerPlaylist", "get playlist of the server at the specified index of the server list", "string", "int", &SQNativeFunctions::IBrowser::GetServerPlaylist);
HSQVM_RegisterFunction(sqvm, "GetServerMap", "get map of the server at the specified index of the server list", "string", "int", &SQNativeFunctions::IBrowser::GetServerMap);
HSQVM_RegisterFunction(sqvm, "GetServerCount", "get number of public servers", "int", "", &SQNativeFunctions::IBrowser::GetServerCount);
// misc main menu functions
HSQVM_RegisterFunction(sqvm, "GetSDKVersion", "get sdk version as a string", "string", "", &SQNativeFunctions::IBrowser::GetSDKVersion);
HSQVM_RegisterFunction(sqvm, "GetPromoData", "get promo data for specified slot type", "string", "int", &SQNativeFunctions::IBrowser::GetPromoData);
// functions for connecting to servers
HSQVM_RegisterFunction(sqvm, "CreateServer", "start server with the specified settings", "void", "string,string,string,int", &SQNativeFunctions::IBrowser::CreateServerFromMenu);
HSQVM_RegisterFunction(sqvm, "SetEncKeyAndConnect", "set the encryption key to that of the specified server and connects to it", "void", "int", &SQNativeFunctions::IBrowser::SetEncKeyAndConnect);
HSQVM_RegisterFunction(sqvm, "JoinPrivateServerFromMenu", "join private server by token", "void", "string", &SQNativeFunctions::IBrowser::JoinPrivateServerFromMenu);
HSQVM_RegisterFunction(sqvm, "GetPrivateServerMessage", "get private server join status message", "string", "string", &SQNativeFunctions::IBrowser::GetPrivateServerMessage);
HSQVM_RegisterFunction(sqvm, "ConnectToIPFromMenu", "join server by ip and encryption key", "void", "string,string", &SQNativeFunctions::IBrowser::ConnectToIPFromMenu);
HSQVM_RegisterFunction(sqvm, "GetAvailableMaps", "gets an array of all the available maps that can be used to host a server", "array<string>", "", &SQNativeFunctions::IBrowser::GetAvailableMaps);
#endif
} }
void RegisterClientScriptFunctions(void* sqvm) void RegisterClientScriptFunctions(void* sqvm)
@ -285,14 +282,13 @@ void RegisterServerScriptFunctions(void* sqvm)
HSQVM_RegisterFunction(sqvm, "ServerNativeTest", "native server function", "void", "", &HSQVM_NativeTest); HSQVM_RegisterFunction(sqvm, "ServerNativeTest", "native server function", "void", "", &HSQVM_NativeTest);
} }
ADDRESS UIVM = (void*)p_SQVM_CreateUIVM.FollowNearCall().FindPatternSelf("48 8B 1D", ADDRESS::Direction::DOWN, 50).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr();
void HSQVM_RegisterOriginFuncs(void* sqvm) void HSQVM_RegisterOriginFuncs(void* sqvm)
{ {
if (sqvm == *UIVM.RCast<void**>()) if (sqvm == *p_SQVM_UIVM.RCast<void**>())
RegisterUIScriptFunctions(sqvm); RegisterUIScriptFunctions(sqvm);
else else
RegisterClientScriptFunctions(sqvm); RegisterClientScriptFunctions(sqvm);
return SQVM_RegisterOriginFuncs(sqvm); return SQVM_RegisterOriginFuncs(sqvm);
} }
@ -300,7 +296,6 @@ void SQVM_Attach()
{ {
DetourAttach((LPVOID*)&SQVM_PrintFunc, &HSQVM_PrintFunc); DetourAttach((LPVOID*)&SQVM_PrintFunc, &HSQVM_PrintFunc);
DetourAttach((LPVOID*)&SQVM_WarningFunc, &HSQVM_WarningFunc); DetourAttach((LPVOID*)&SQVM_WarningFunc, &HSQVM_WarningFunc);
DetourAttach((LPVOID*)&SQVM_WarningCmd, &HSQVM_WarningCmd);
DetourAttach((LPVOID*)&SQVM_LoadRson, &HSQVM_LoadRson); DetourAttach((LPVOID*)&SQVM_LoadRson, &HSQVM_LoadRson);
DetourAttach((LPVOID*)&SQVM_LoadScript, &HSQVM_LoadScript); DetourAttach((LPVOID*)&SQVM_LoadScript, &HSQVM_LoadScript);
DetourAttach((LPVOID*)&SQVM_RegisterOriginFuncs, &HSQVM_RegisterOriginFuncs); DetourAttach((LPVOID*)&SQVM_RegisterOriginFuncs, &HSQVM_RegisterOriginFuncs);
@ -310,7 +305,6 @@ void SQVM_Detach()
{ {
DetourDetach((LPVOID*)&SQVM_PrintFunc, &HSQVM_PrintFunc); DetourDetach((LPVOID*)&SQVM_PrintFunc, &HSQVM_PrintFunc);
DetourDetach((LPVOID*)&SQVM_WarningFunc, &HSQVM_WarningFunc); DetourDetach((LPVOID*)&SQVM_WarningFunc, &HSQVM_WarningFunc);
DetourDetach((LPVOID*)&SQVM_WarningCmd, &HSQVM_WarningCmd);
DetourDetach((LPVOID*)&SQVM_LoadRson, &HSQVM_LoadRson); DetourDetach((LPVOID*)&SQVM_LoadRson, &HSQVM_LoadRson);
DetourDetach((LPVOID*)&SQVM_LoadScript, &HSQVM_LoadScript); DetourDetach((LPVOID*)&SQVM_LoadScript, &HSQVM_LoadScript);
DetourDetach((LPVOID*)&SQVM_RegisterOriginFuncs, &HSQVM_RegisterOriginFuncs); DetourDetach((LPVOID*)&SQVM_RegisterOriginFuncs, &HSQVM_RegisterOriginFuncs);

View File

@ -27,6 +27,28 @@ struct SQFuncRegistration
} }
}; };
const static std::string SQVM_LOG_T[4] =
{
"Script(S):",
"Script(C):",
"Script(U):",
"Script(X):"
};
const static std::string SQVM_ANSI_LOG_T[4] =
{
"\u001b[94mScript(S):",
"\u001b[90mScript(C):",
"\u001b[33mScript(U):",
"\u001b[90mScript(X):"
};
typedef int SQRESULT;
#define SQ_OK (1)
#define SQ_ERROR (-1)
#define SQ_FAILED(res) (res<0)
#define SQ_SUCCEEDED(res) (res>=0)
namespace namespace
{ {
/* ==== SQUIRREL ======================================================================================================================================================== */ /* ==== SQUIRREL ======================================================================================================================================================== */
@ -51,15 +73,11 @@ namespace
ADDRESS p_SQVM_RegisterFunc = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x38\x45\x0F\xB6\xC8", "xxxxxxxx"); /*48 83 EC 38 45 0F B6 C8*/ ADDRESS p_SQVM_RegisterFunc = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x83\xEC\x38\x45\x0F\xB6\xC8", "xxxxxxxx"); /*48 83 EC 38 45 0F B6 C8*/
void* (*SQVM_RegisterFunc)(void* sqvm, SQFuncRegistration* sqFunc, int a1) = (void* (*)(void*, SQFuncRegistration*, int))p_SQVM_RegisterFunc.GetPtr(); void* (*SQVM_RegisterFunc)(void* sqvm, SQFuncRegistration* sqFunc, int a1) = (void* (*)(void*, SQFuncRegistration*, int))p_SQVM_RegisterFunc.GetPtr();
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) ADDRESS p_SQVM_CreateUIVM = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x48\x8B\x1D\x00\x00\x00\x00\xC6\x05\x00\x00\x00\x00\x00", "xxxxxxxxx????xx?????"); /*40 53 48 83 EC 20 48 8B 1D ? ? ? ? C6 05 ? ? ? ? ?*/
ADDRESS p_SQVM_CreateUIVM = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\xE8\x00\x00\x00\x00\x84\xC0\x74\x18\xE8\x00\x00\x00\x00", "x????xxxxx????") bool (*SQVM_CreateUIVM)() = (bool(*)())p_SQVM_CreateUIVM.GetPtr();
bool (*SQVM_CreateUIVM)() = (bool(*)())p_SQVM_CreateUIVM.FollowNearCall().GetPtr(); ADDRESS p_SQVM_UIVM = (void*)p_SQVM_CreateUIVM.FindPatternSelf("48 8B 1D", ADDRESS::Direction::DOWN, 50).ResolveRelativeAddressSelf(0x3, 0x7).GetPtr();
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
ADDRESS p_SQVM_CreateUIVM = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\xE8\x00\x00\x00\x00\x84\xC0\x74\xE0\x44\x38\x25\x00\x00\x00\x00", "x????xxxxxxx????");
bool (*SQVM_CreateUIVM)() = (bool(*)())p_SQVM_CreateUIVM.FollowNearCall().GetPtr();
#endif
ADDRESS p_SQVM_RegisterOriginFuncs = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\xE8\x00\x00\x00\x00\x48\x8B\x0D\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x48\x8B\x05\x00\x00\x00\x00\xC7\x05\x00\x00\x00\x00\x00\x00\x00\x00", "x????xxx????xxx????x????xxx????xx????????"); ADDRESS p_SQVM_RegisterOriginFuncs = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\xE8\x00\x00\x00\x00\x48\x8B\x0D\x00\x00\x00\x00\x48\x8D\x15\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x48\x8B\x05\x00\x00\x00\x00\xC7\x05\x00\x00\x00\x00\x00\x00\x00\x00", "x????xxx????xxx????x????xxx????xx????????"); /*E8 ? ? ? ? 48 8B 0D ? ? ? ? 48 8D 15 ? ? ? ? E8 ? ? ? ? 48 8B 05 ? ? ? ? C7 05 ? ? ? ? ? ? ? ?*/
void (*SQVM_RegisterOriginFuncs)(void* sqvm) = (void(*)(void*))p_SQVM_RegisterOriginFuncs.FollowNearCall().GetPtr(); void (*SQVM_RegisterOriginFuncs)(void* sqvm) = (void(*)(void*))p_SQVM_RegisterOriginFuncs.FollowNearCall().GetPtr();
} }
@ -69,15 +87,11 @@ bool HSQVM_LoadScript(void* sqvm, const char* szScriptPath, const char* szScript
void HSQVM_RegisterFunction(void* sqvm, const char* szName, const char* szHelpString, const char* szRetValType, const char* szArgTypes, void* pFunction); void HSQVM_RegisterFunction(void* sqvm, const char* szName, const char* szHelpString, const char* szRetValType, const char* szArgTypes, void* pFunction);
int HSQVM_NativeTest(void* sqvm); int HSQVM_NativeTest(void* sqvm);
void HSQVM_RegisterOriginFuncs(void* sqvm); void HSQVM_RegisterOriginFuncs(void* sqvm);
void SQVM_Attach(); void SQVM_Attach();
void SQVM_Detach(); void SQVM_Detach();
///////////////////////////////////////////////////////////////////////////////
extern bool g_bSQVM_WarnFuncCalled;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class HSQVM : public IDetour class HSQVM : public IDetour
{ {

Binary file not shown.

Binary file not shown.

1783
r5dev/thirdparty/detours/src/creatwth.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

2597
r5dev/thirdparty/detours/src/detours.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

4306
r5dev/thirdparty/detours/src/disasm.cpp vendored Normal file

File diff suppressed because it is too large Load Diff

932
r5dev/thirdparty/detours/src/modules.cpp vendored Normal file
View File

@ -0,0 +1,932 @@
//////////////////////////////////////////////////////////////////////////////
//
// Module Enumeration Functions (modules.cpp of detours.lib)
//
// Microsoft Research Detours Package, Version 4.0.1
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Module enumeration functions.
//
// #define DETOUR_DEBUG 1
#define DETOURS_INTERNAL
#include "../include/detours.h"
#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
#error detours.h version mismatch
#endif
#define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]
#define IAT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT]
//////////////////////////////////////////////////////////////////////////////
//
const GUID DETOUR_EXE_RESTORE_GUID = {
0xbda26f34, 0xbc82, 0x4829,
{ 0x9e, 0x64, 0x74, 0x2c, 0x4, 0xc8, 0x4f, 0xa0 } };
//////////////////////////////////////////////////////////////////////////////
//
PDETOUR_SYM_INFO DetourLoadImageHlp(VOID)
{
static DETOUR_SYM_INFO symInfo;
static PDETOUR_SYM_INFO pSymInfo = NULL;
static BOOL failed = false;
if (failed) {
return NULL;
}
if (pSymInfo != NULL) {
return pSymInfo;
}
ZeroMemory(&symInfo, sizeof(symInfo));
// Create a real handle to the process.
#if 0
DuplicateHandle(GetCurrentProcess(),
GetCurrentProcess(),
GetCurrentProcess(),
&symInfo.hProcess,
0,
FALSE,
DUPLICATE_SAME_ACCESS);
#else
symInfo.hProcess = GetCurrentProcess();
#endif
symInfo.hDbgHelp = LoadLibraryExW(L"dbghelp.dll", NULL, 0);
if (symInfo.hDbgHelp == NULL) {
abort:
failed = true;
if (symInfo.hDbgHelp != NULL) {
FreeLibrary(symInfo.hDbgHelp);
}
symInfo.pfImagehlpApiVersionEx = NULL;
symInfo.pfSymInitialize = NULL;
symInfo.pfSymSetOptions = NULL;
symInfo.pfSymGetOptions = NULL;
symInfo.pfSymLoadModule64 = NULL;
symInfo.pfSymGetModuleInfo64 = NULL;
symInfo.pfSymFromName = NULL;
return NULL;
}
symInfo.pfImagehlpApiVersionEx
= (PF_ImagehlpApiVersionEx)GetProcAddress(symInfo.hDbgHelp,
"ImagehlpApiVersionEx");
symInfo.pfSymInitialize
= (PF_SymInitialize)GetProcAddress(symInfo.hDbgHelp, "SymInitialize");
symInfo.pfSymSetOptions
= (PF_SymSetOptions)GetProcAddress(symInfo.hDbgHelp, "SymSetOptions");
symInfo.pfSymGetOptions
= (PF_SymGetOptions)GetProcAddress(symInfo.hDbgHelp, "SymGetOptions");
symInfo.pfSymLoadModule64
= (PF_SymLoadModule64)GetProcAddress(symInfo.hDbgHelp, "SymLoadModule64");
symInfo.pfSymGetModuleInfo64
= (PF_SymGetModuleInfo64)GetProcAddress(symInfo.hDbgHelp, "SymGetModuleInfo64");
symInfo.pfSymFromName
= (PF_SymFromName)GetProcAddress(symInfo.hDbgHelp, "SymFromName");
API_VERSION av;
ZeroMemory(&av, sizeof(av));
av.MajorVersion = API_VERSION_NUMBER;
if (symInfo.pfImagehlpApiVersionEx == NULL ||
symInfo.pfSymInitialize == NULL ||
symInfo.pfSymLoadModule64 == NULL ||
symInfo.pfSymGetModuleInfo64 == NULL ||
symInfo.pfSymFromName == NULL) {
goto abort;
}
symInfo.pfImagehlpApiVersionEx(&av);
if (av.MajorVersion < API_VERSION_NUMBER) {
goto abort;
}
if (!symInfo.pfSymInitialize(symInfo.hProcess, NULL, FALSE)) {
// We won't retry the initialize if it fails.
goto abort;
}
if (symInfo.pfSymGetOptions != NULL && symInfo.pfSymSetOptions != NULL) {
DWORD dw = symInfo.pfSymGetOptions();
dw &= ~(SYMOPT_CASE_INSENSITIVE |
SYMOPT_UNDNAME |
SYMOPT_DEFERRED_LOADS |
0);
dw |= (
#if defined(SYMOPT_EXACT_SYMBOLS)
SYMOPT_EXACT_SYMBOLS |
#endif
#if defined(SYMOPT_NO_UNQUALIFIED_LOADS)
SYMOPT_NO_UNQUALIFIED_LOADS |
#endif
SYMOPT_DEFERRED_LOADS |
#if defined(SYMOPT_FAIL_CRITICAL_ERRORS)
SYMOPT_FAIL_CRITICAL_ERRORS |
#endif
#if defined(SYMOPT_INCLUDE_32BIT_MODULES)
SYMOPT_INCLUDE_32BIT_MODULES |
#endif
0);
symInfo.pfSymSetOptions(dw);
}
pSymInfo = &symInfo;
return pSymInfo;
}
PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule,
_In_ LPCSTR pszFunction)
{
if (pszFunction == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/////////////////////////////////////////////// First, try GetProcAddress.
//
#pragma prefast(suppress:28752, "We don't do the unicode conversion for LoadLibraryExA.")
HMODULE hModule = LoadLibraryExA(pszModule, NULL, 0);
if (hModule == NULL) {
return NULL;
}
PBYTE pbCode = (PBYTE)GetProcAddress(hModule, pszFunction);
if (pbCode) {
return pbCode;
}
////////////////////////////////////////////////////// Then try ImageHelp.
//
DETOUR_TRACE(("DetourFindFunction(%hs, %hs)\n", pszModule, pszFunction));
PDETOUR_SYM_INFO pSymInfo = DetourLoadImageHlp();
if (pSymInfo == NULL) {
DETOUR_TRACE(("DetourLoadImageHlp failed: %lu\n",
GetLastError()));
return NULL;
}
if (pSymInfo->pfSymLoadModule64(pSymInfo->hProcess, NULL,
(PCHAR)pszModule, NULL,
(DWORD64)hModule, 0) == 0) {
if (ERROR_SUCCESS != GetLastError()) {
DETOUR_TRACE(("SymLoadModule64(%p) failed: %lu\n",
pSymInfo->hProcess, GetLastError()));
return NULL;
}
}
HRESULT hrRet;
CHAR szFullName[512];
IMAGEHLP_MODULE64 modinfo;
ZeroMemory(&modinfo, sizeof(modinfo));
modinfo.SizeOfStruct = sizeof(modinfo);
if (!pSymInfo->pfSymGetModuleInfo64(pSymInfo->hProcess, (DWORD64)hModule, &modinfo)) {
DETOUR_TRACE(("SymGetModuleInfo64(%p, %p) failed: %lu\n",
pSymInfo->hProcess, hModule, GetLastError()));
return NULL;
}
hrRet = StringCchCopyA(szFullName, sizeof(szFullName)/sizeof(CHAR), modinfo.ModuleName);
if (FAILED(hrRet)) {
DETOUR_TRACE(("StringCchCopyA failed: %08lx\n", hrRet));
return NULL;
}
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), "!");
if (FAILED(hrRet)) {
DETOUR_TRACE(("StringCchCatA failed: %08lx\n", hrRet));
return NULL;
}
hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), pszFunction);
if (FAILED(hrRet)) {
DETOUR_TRACE(("StringCchCatA failed: %08lx\n", hrRet));
return NULL;
}
struct CFullSymbol : SYMBOL_INFO {
CHAR szRestOfName[512];
} symbol;
ZeroMemory(&symbol, sizeof(symbol));
//symbol.ModBase = (ULONG64)hModule;
symbol.SizeOfStruct = sizeof(SYMBOL_INFO);
#ifdef DBHLPAPI
symbol.MaxNameLen = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]);
#else
symbol.MaxNameLength = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]);
#endif
if (!pSymInfo->pfSymFromName(pSymInfo->hProcess, szFullName, &symbol)) {
DETOUR_TRACE(("SymFromName(%hs) failed: %lu\n", szFullName, GetLastError()));
return NULL;
}
#if defined(DETOURS_IA64)
// On the IA64, we get a raw code pointer from the symbol engine
// and have to convert it to a wrapped [code pointer, global pointer].
//
PPLABEL_DESCRIPTOR pldEntry = (PPLABEL_DESCRIPTOR)DetourGetEntryPoint(hModule);
PPLABEL_DESCRIPTOR pldSymbol = new PLABEL_DESCRIPTOR;
pldSymbol->EntryPoint = symbol.Address;
pldSymbol->GlobalPointer = pldEntry->GlobalPointer;
return (PBYTE)pldSymbol;
#elif defined(DETOURS_ARM)
// On the ARM, we get a raw code pointer, which we must convert into a
// valied Thumb2 function pointer.
return DETOURS_PBYTE_TO_PFUNC(symbol.Address);
#else
return (PBYTE)symbol.Address;
#endif
}
//////////////////////////////////////////////////// Module Image Functions.
//
HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast)
{
PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY;
MEMORY_BASIC_INFORMATION mbi;
ZeroMemory(&mbi, sizeof(mbi));
// Find the next memory region that contains a mapped PE image.
//
for (;; pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) {
if (VirtualQuery(pbLast, &mbi, sizeof(mbi)) <= 0) {
break;
}
// Skip uncommitted regions and guard pages.
//
if ((mbi.State != MEM_COMMIT) ||
((mbi.Protect & 0xff) == PAGE_NOACCESS) ||
(mbi.Protect & PAGE_GUARD)) {
continue;
}
__try {
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pbLast;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE ||
(DWORD)pDosHeader->e_lfanew > mbi.RegionSize ||
(DWORD)pDosHeader->e_lfanew < sizeof(*pDosHeader)) {
continue;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
continue;
}
SetLastError(NO_ERROR);
return (HMODULE)pDosHeader;
}
#pragma prefast(suppress:28940, "A bad pointer means this probably isn't a PE header.")
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
continue;
}
}
return NULL;
}
PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
if (hModule == NULL) {
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
}
__try {
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return NULL;
}
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
PDETOUR_CLR_HEADER pClrHeader = NULL;
if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
if (((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.VirtualAddress != 0 &&
((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.Size != 0) {
pClrHeader = (PDETOUR_CLR_HEADER)
(((PBYTE)pDosHeader)
+ ((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.VirtualAddress);
}
}
else if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
if (((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.VirtualAddress != 0 &&
((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.Size != 0) {
pClrHeader = (PDETOUR_CLR_HEADER)
(((PBYTE)pDosHeader)
+ ((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.VirtualAddress);
}
}
if (pClrHeader != NULL) {
// For MSIL assemblies, we want to use the _Cor entry points.
HMODULE hClr = GetModuleHandleW(L"MSCOREE.DLL");
if (hClr == NULL) {
return NULL;
}
SetLastError(NO_ERROR);
return (PVOID)GetProcAddress(hClr, "_CorExeMain");
}
SetLastError(NO_ERROR);
// Pure resource DLLs have neither an entry point nor CLR information
// so handle them by returning NULL (LastError is NO_ERROR)
if (pNtHeader->OptionalHeader.AddressOfEntryPoint == 0) {
return NULL;
}
return ((PBYTE)pDosHeader) +
pNtHeader->OptionalHeader.AddressOfEntryPoint;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
}
ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
if (hModule == NULL) {
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
}
__try {
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return NULL;
}
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
SetLastError(NO_ERROR);
return (pNtHeader->OptionalHeader.SizeOfImage);
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
}
HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr)
{
MEMORY_BASIC_INFORMATION mbi;
ZeroMemory(&mbi, sizeof(mbi));
__try {
if (VirtualQuery(pvAddr, &mbi, sizeof(mbi)) <= 0) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
// Skip uncommitted regions and guard pages.
//
if ((mbi.State != MEM_COMMIT) ||
((mbi.Protect & 0xff) == PAGE_NOACCESS) ||
(mbi.Protect & PAGE_GUARD)) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return NULL;
}
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
SetLastError(NO_ERROR);
return (HMODULE)pDosHeader;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return NULL;
}
}
static inline PBYTE RvaAdjust(_Pre_notnull_ PIMAGE_DOS_HEADER pDosHeader, _In_ DWORD raddr)
{
if (raddr != NULL) {
return ((PBYTE)pDosHeader) + raddr;
}
return NULL;
}
BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule,
_In_opt_ PVOID pContext,
_In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport)
{
if (pfExport == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
if (hModule == NULL) {
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
}
__try {
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return FALSE;
}
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
PIMAGE_EXPORT_DIRECTORY pExportDir
= (PIMAGE_EXPORT_DIRECTORY)
RvaAdjust(pDosHeader,
pNtHeader->OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
if (pExportDir == NULL) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
PBYTE pExportDirEnd = (PBYTE)pExportDir + pNtHeader->OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
PDWORD pdwFunctions = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfFunctions);
PDWORD pdwNames = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNames);
PWORD pwOrdinals = (PWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNameOrdinals);
for (DWORD nFunc = 0; nFunc < pExportDir->NumberOfFunctions; nFunc++) {
PBYTE pbCode = (pdwFunctions != NULL)
? (PBYTE)RvaAdjust(pDosHeader, pdwFunctions[nFunc]) : NULL;
PCHAR pszName = NULL;
// if the pointer is in the export region, then it is a forwarder.
if (pbCode > (PBYTE)pExportDir && pbCode < pExportDirEnd) {
pbCode = NULL;
}
for (DWORD n = 0; n < pExportDir->NumberOfNames; n++) {
if (pwOrdinals[n] == nFunc) {
pszName = (pdwNames != NULL)
? (PCHAR)RvaAdjust(pDosHeader, pdwNames[n]) : NULL;
break;
}
}
ULONG nOrdinal = pExportDir->Base + nFunc;
if (!pfExport(pContext, nOrdinal, pszName, pbCode)) {
break;
}
}
SetLastError(NO_ERROR);
return TRUE;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
}
BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule,
_In_opt_ PVOID pContext,
_In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
_In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFunc)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
if (hModule == NULL) {
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
}
__try {
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return FALSE;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return FALSE;
}
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
PIMAGE_IMPORT_DESCRIPTOR iidp
= (PIMAGE_IMPORT_DESCRIPTOR)
RvaAdjust(pDosHeader,
pNtHeader->OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
if (iidp == NULL) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
for (; iidp->OriginalFirstThunk != 0; iidp++) {
PCSTR pszName = (PCHAR)RvaAdjust(pDosHeader, iidp->Name);
if (pszName == NULL) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
PIMAGE_THUNK_DATA pThunks = (PIMAGE_THUNK_DATA)
RvaAdjust(pDosHeader, iidp->OriginalFirstThunk);
PVOID * pAddrs = (PVOID *)
RvaAdjust(pDosHeader, iidp->FirstThunk);
HMODULE hFile = DetourGetContainingModule(pAddrs[0]);
if (pfImportFile != NULL) {
if (!pfImportFile(pContext, hFile, pszName)) {
break;
}
}
DWORD nNames = 0;
if (pThunks) {
for (; pThunks[nNames].u1.Ordinal; nNames++) {
DWORD nOrdinal = 0;
PCSTR pszFunc = NULL;
if (IMAGE_SNAP_BY_ORDINAL(pThunks[nNames].u1.Ordinal)) {
nOrdinal = (DWORD)IMAGE_ORDINAL(pThunks[nNames].u1.Ordinal);
}
else {
pszFunc = (PCSTR)RvaAdjust(pDosHeader,
(DWORD)pThunks[nNames].u1.AddressOfData + 2);
}
if (pfImportFunc != NULL) {
if (!pfImportFunc(pContext,
nOrdinal,
pszFunc,
&pAddrs[nNames])) {
break;
}
}
}
if (pfImportFunc != NULL) {
pfImportFunc(pContext, 0, NULL, NULL);
}
}
}
if (pfImportFile != NULL) {
pfImportFile(pContext, NULL, NULL);
}
SetLastError(NO_ERROR);
return TRUE;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
}
// Context for DetourEnumerateImportsThunk, which adapts "regular" callbacks for use with "Ex".
struct _DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT
{
PVOID pContext;
PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc;
};
// Callback for DetourEnumerateImportsEx that adapts DetourEnumerateImportsEx
// for use with a DetourEnumerateImports callback -- derefence the IAT and pass the value on.
static
BOOL
CALLBACK
DetourEnumerateImportsThunk(_In_ PVOID VoidContext,
_In_ DWORD nOrdinal,
_In_opt_ PCSTR pszFunc,
_In_opt_ PVOID* ppvFunc)
{
_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const * const
pContext = (_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT*)VoidContext;
return pContext->pfImportFunc(pContext->pContext, nOrdinal, pszFunc, ppvFunc ? *ppvFunc : NULL);
}
BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule,
_In_opt_ PVOID pContext,
_In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
_In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc)
{
if (pfImportFile == NULL || pfImportFunc == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const context = { pContext, pfImportFunc };
return DetourEnumerateImportsEx(hModule,
(PVOID)&context,
pfImportFile,
&DetourEnumerateImportsThunk);
}
static PDETOUR_LOADED_BINARY WINAPI GetPayloadSectionFromModule(HMODULE hModule)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
if (hModule == NULL) {
pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL);
}
__try {
#pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL.
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return NULL;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return NULL;
}
if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
PIMAGE_SECTION_HEADER pSectionHeaders
= (PIMAGE_SECTION_HEADER)((PBYTE)pNtHeader
+ sizeof(pNtHeader->Signature)
+ sizeof(pNtHeader->FileHeader)
+ pNtHeader->FileHeader.SizeOfOptionalHeader);
for (DWORD n = 0; n < pNtHeader->FileHeader.NumberOfSections; n++) {
if (strcmp((PCHAR)pSectionHeaders[n].Name, ".detour") == 0) {
if (pSectionHeaders[n].VirtualAddress == 0 ||
pSectionHeaders[n].SizeOfRawData == 0) {
break;
}
PBYTE pbData = (PBYTE)pDosHeader + pSectionHeaders[n].VirtualAddress;
DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pbData;
if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
break;
}
if (pHeader->nDataOffset == 0) {
pHeader->nDataOffset = pHeader->cbHeaderSize;
}
SetLastError(NO_ERROR);
return (PBYTE)pHeader;
}
}
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return NULL;
}
}
DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule)
{
PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule);
if (pBinary == NULL) {
// Error set by GetPayloadSectionFromModule.
return 0;
}
__try {
DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary;
if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
SetLastError(ERROR_INVALID_HANDLE);
return 0;
}
SetLastError(NO_ERROR);
return pHeader->cbDataSize;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_INVALID_HANDLE);
return 0;
}
}
_Writable_bytes_(*pcbData)
_Readable_bytes_(*pcbData)
_Success_(return != NULL)
PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule,
_In_ REFGUID rguid,
_Out_opt_ DWORD *pcbData)
{
PBYTE pbData = NULL;
if (pcbData) {
*pcbData = 0;
}
PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule);
if (pBinary == NULL) {
// Error set by GetPayloadSectionFromModule.
return NULL;
}
__try {
DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary;
if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) ||
pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return NULL;
}
PBYTE pbBeg = ((PBYTE)pHeader) + pHeader->nDataOffset;
PBYTE pbEnd = ((PBYTE)pHeader) + pHeader->cbDataSize;
for (pbData = pbBeg; pbData < pbEnd;) {
DETOUR_SECTION_RECORD *pSection = (DETOUR_SECTION_RECORD *)pbData;
if (DetourAreSameGuid(pSection->guid, rguid)) {
if (pcbData) {
*pcbData = pSection->cbBytes - sizeof(*pSection);
}
SetLastError(NO_ERROR);
return (PBYTE)(pSection + 1);
}
pbData = (PBYTE)pSection + pSection->cbBytes;
}
SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
}
_Writable_bytes_(*pcbData)
_Readable_bytes_(*pcbData)
_Success_(return != NULL)
PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid,
_Out_opt_ DWORD *pcbData)
{
for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) {
PVOID pvData;
pvData = DetourFindPayload(hMod, rguid, pcbData);
if (pvData != NULL) {
return pvData;
}
}
SetLastError(ERROR_MOD_NOT_FOUND);
return NULL;
}
BOOL WINAPI DetourFreePayload(_In_ PVOID pvData)
{
BOOL fSucceeded = FALSE;
// If you have any doubts about the following code, please refer to the comments in DetourCopyPayloadToProcess.
HMODULE hModule = DetourGetContainingModule(pvData);
DETOUR_ASSERT(hModule != NULL);
if (hModule != NULL) {
fSucceeded = VirtualFree(hModule, 0, MEM_RELEASE);
DETOUR_ASSERT(fSucceeded);
if (fSucceeded) {
hModule = NULL;
}
}
return fSucceeded;
}
BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData,
_In_ DWORD cbData)
{
PDETOUR_EXE_RESTORE pder = (PDETOUR_EXE_RESTORE)pvData;
if (pder->cb != sizeof(*pder) || pder->cb > cbData) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return FALSE;
}
DWORD dwPermIdh = ~0u;
DWORD dwPermInh = ~0u;
DWORD dwPermClr = ~0u;
DWORD dwIgnore;
BOOL fSucceeded = FALSE;
BOOL fUpdated32To64 = FALSE;
if (pder->pclr != NULL && pder->clr.Flags != ((PDETOUR_CLR_HEADER)pder->pclr)->Flags) {
// If we had to promote the 32/64-bit agnostic IL to 64-bit, we can't restore
// that.
fUpdated32To64 = TRUE;
}
if (DetourVirtualProtectSameExecute(pder->pidh, pder->cbidh,
PAGE_EXECUTE_READWRITE, &dwPermIdh)) {
if (DetourVirtualProtectSameExecute(pder->pinh, pder->cbinh,
PAGE_EXECUTE_READWRITE, &dwPermInh)) {
CopyMemory(pder->pidh, &pder->idh, pder->cbidh);
CopyMemory(pder->pinh, &pder->inh, pder->cbinh);
if (pder->pclr != NULL && !fUpdated32To64) {
if (DetourVirtualProtectSameExecute(pder->pclr, pder->cbclr,
PAGE_EXECUTE_READWRITE, &dwPermClr)) {
CopyMemory(pder->pclr, &pder->clr, pder->cbclr);
VirtualProtect(pder->pclr, pder->cbclr, dwPermClr, &dwIgnore);
fSucceeded = TRUE;
}
}
else {
fSucceeded = TRUE;
}
VirtualProtect(pder->pinh, pder->cbinh, dwPermInh, &dwIgnore);
}
VirtualProtect(pder->pidh, pder->cbidh, dwPermIdh, &dwIgnore);
}
// Delete the payload after successful recovery to prevent repeated restore
if (fSucceeded) {
DetourFreePayload(pder);
pder = NULL;
}
return fSucceeded;
}
BOOL WINAPI DetourRestoreAfterWith()
{
PVOID pvData;
DWORD cbData;
pvData = DetourFindPayloadEx(DETOUR_EXE_RESTORE_GUID, &cbData);
if (pvData != NULL && cbData != 0) {
return DetourRestoreAfterWithEx(pvData, cbData);
}
SetLastError(ERROR_MOD_NOT_FOUND);
return FALSE;
}
// End of File

View File

@ -0,0 +1,335 @@
//////////////////////////////////////////////////////////////////////////////
//
// Add DLLs to a module import table (uimports.cpp of detours.lib)
//
// Microsoft Research Detours Package, Version 4.0.1
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Note that this file is included into creatwth.cpp one or more times
// (once for each supported module format).
//
#include "../include/detours.h"
#if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH
#error detours.h version mismatch
#endif
// UpdateImports32 aka UpdateImports64
static BOOL UPDATE_IMPORTS_XX(HANDLE hProcess,
HMODULE hModule,
__in_ecount(nDlls) LPCSTR *plpDlls,
DWORD nDlls)
{
BOOL fSucceeded = FALSE;
DWORD cbNew = 0;
BYTE * pbNew = NULL;
DWORD i;
SIZE_T cbRead;
DWORD n;
PBYTE pbModule = (PBYTE)hModule;
IMAGE_DOS_HEADER idh;
ZeroMemory(&idh, sizeof(idh));
if (!ReadProcessMemory(hProcess, pbModule, &idh, sizeof(idh), &cbRead)
|| cbRead < sizeof(idh)) {
DETOUR_TRACE(("ReadProcessMemory(idh@%p..%p) failed: %lu\n",
pbModule, pbModule + sizeof(idh), GetLastError()));
finish:
if (pbNew != NULL) {
delete[] pbNew;
pbNew = NULL;
}
return fSucceeded;
}
IMAGE_NT_HEADERS_XX inh;
ZeroMemory(&inh, sizeof(inh));
if (!ReadProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), &cbRead)
|| cbRead < sizeof(inh)) {
DETOUR_TRACE(("ReadProcessMemory(inh@%p..%p) failed: %lu\n",
pbModule + idh.e_lfanew,
pbModule + idh.e_lfanew + sizeof(inh),
GetLastError()));
goto finish;
}
if (inh.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC_XX) {
DETOUR_TRACE(("Wrong size image (%04x != %04x).\n",
inh.OptionalHeader.Magic, IMAGE_NT_OPTIONAL_HDR_MAGIC_XX));
SetLastError(ERROR_INVALID_BLOCK);
goto finish;
}
// Zero out the bound table so loader doesn't use it instead of our new table.
inh.BOUND_DIRECTORY.VirtualAddress = 0;
inh.BOUND_DIRECTORY.Size = 0;
// Find the size of the mapped file.
DWORD dwSec = idh.e_lfanew +
FIELD_OFFSET(IMAGE_NT_HEADERS_XX, OptionalHeader) +
inh.FileHeader.SizeOfOptionalHeader;
for (i = 0; i < inh.FileHeader.NumberOfSections; i++) {
IMAGE_SECTION_HEADER ish;
ZeroMemory(&ish, sizeof(ish));
if (!ReadProcessMemory(hProcess, pbModule + dwSec + sizeof(ish) * i, &ish,
sizeof(ish), &cbRead)
|| cbRead < sizeof(ish)) {
DETOUR_TRACE(("ReadProcessMemory(ish@%p..%p) failed: %lu\n",
pbModule + dwSec + sizeof(ish) * i,
pbModule + dwSec + sizeof(ish) * (i + 1),
GetLastError()));
goto finish;
}
DETOUR_TRACE(("ish[%lu] : va=%08lx sr=%lu\n", i, ish.VirtualAddress, ish.SizeOfRawData));
// If the linker didn't suggest an IAT in the data directories, the
// loader will look for the section of the import directory to be used
// for this instead. Since we put out new IMPORT_DIRECTORY outside any
// section boundary, the loader will not find it. So we provide one
// explicitly to avoid the search.
//
if (inh.IAT_DIRECTORY.VirtualAddress == 0 &&
inh.IMPORT_DIRECTORY.VirtualAddress >= ish.VirtualAddress &&
inh.IMPORT_DIRECTORY.VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData) {
inh.IAT_DIRECTORY.VirtualAddress = ish.VirtualAddress;
inh.IAT_DIRECTORY.Size = ish.SizeOfRawData;
}
}
if (inh.IMPORT_DIRECTORY.VirtualAddress != 0 && inh.IMPORT_DIRECTORY.Size == 0) {
// Don't worry about changing the PE file,
// because the load information of the original PE header has been saved and will be restored.
// The change here is just for the following code to work normally
PIMAGE_IMPORT_DESCRIPTOR pImageImport = (PIMAGE_IMPORT_DESCRIPTOR)(pbModule + inh.IMPORT_DIRECTORY.VirtualAddress);
do {
IMAGE_IMPORT_DESCRIPTOR ImageImport;
if (!ReadProcessMemory(hProcess, pImageImport, &ImageImport, sizeof(ImageImport), NULL)) {
DETOUR_TRACE(("ReadProcessMemory failed: %lu\n", GetLastError()));
goto finish;
}
inh.IMPORT_DIRECTORY.Size += sizeof(IMAGE_IMPORT_DESCRIPTOR);
if (!ImageImport.Name) {
break;
}
++pImageImport;
} while (TRUE);
DWORD dwLastError = GetLastError();
OutputDebugString(TEXT("[This PE file has an import table, but the import table size is marked as 0. This is an error.")
TEXT("If it is not repaired, the launched program will not work properly, Detours has automatically repaired its import table size for you! ! !]\r\n"));
if (GetLastError() != dwLastError) {
SetLastError(dwLastError);
}
}
DETOUR_TRACE((" Imports: %p..%p\n",
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress +
inh.IMPORT_DIRECTORY.Size));
// Calculate new import directory size. Note that since inh is from another
// process, inh could have been corrupted. We need to protect against
// integer overflow in allocation calculations.
DWORD nOldDlls = inh.IMPORT_DIRECTORY.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
DWORD obRem;
if (DWordMult(sizeof(IMAGE_IMPORT_DESCRIPTOR), nDlls, &obRem) != S_OK) {
DETOUR_TRACE(("too many new DLLs.\n"));
goto finish;
}
DWORD obOld;
if (DWordAdd(obRem, sizeof(IMAGE_IMPORT_DESCRIPTOR) * nOldDlls, &obOld) != S_OK) {
DETOUR_TRACE(("DLL entries overflow.\n"));
goto finish;
}
DWORD obTab = PadToDwordPtr(obOld);
// Check for integer overflow.
if (obTab < obOld) {
DETOUR_TRACE(("DLL entries padding overflow.\n"));
goto finish;
}
DWORD stSize;
if (DWordMult(sizeof(DWORD_XX) * 4, nDlls, &stSize) != S_OK) {
DETOUR_TRACE(("String table overflow.\n"));
goto finish;
}
DWORD obDll;
if (DWordAdd(obTab, stSize, &obDll) != S_OK) {
DETOUR_TRACE(("Import table size overflow\n"));
goto finish;
}
DWORD obStr = obDll;
cbNew = obStr;
for (n = 0; n < nDlls; n++) {
if (DWordAdd(cbNew, PadToDword((DWORD)strlen(plpDlls[n]) + 1), &cbNew) != S_OK) {
DETOUR_TRACE(("Overflow adding string table entry\n"));
goto finish;
}
}
pbNew = new BYTE [cbNew];
if (pbNew == NULL) {
DETOUR_TRACE(("new BYTE [cbNew] failed.\n"));
goto finish;
}
ZeroMemory(pbNew, cbNew);
PBYTE pbBase = pbModule;
PBYTE pbNext = pbBase
+ inh.OptionalHeader.BaseOfCode
+ inh.OptionalHeader.SizeOfCode
+ inh.OptionalHeader.SizeOfInitializedData
+ inh.OptionalHeader.SizeOfUninitializedData;
if (pbBase < pbNext) {
pbBase = pbNext;
}
DETOUR_TRACE(("pbBase = %p\n", pbBase));
PBYTE pbNewIid = FindAndAllocateNearBase(hProcess, pbModule, pbBase, cbNew);
if (pbNewIid == NULL) {
DETOUR_TRACE(("FindAndAllocateNearBase failed.\n"));
goto finish;
}
PIMAGE_IMPORT_DESCRIPTOR piid = (PIMAGE_IMPORT_DESCRIPTOR)pbNew;
IMAGE_THUNK_DATAXX *pt = NULL;
DWORD obBase = (DWORD)(pbNewIid - pbModule);
DWORD dwProtect = 0;
if (inh.IMPORT_DIRECTORY.VirtualAddress != 0) {
// Read the old import directory if it exists.
DETOUR_TRACE(("IMPORT_DIRECTORY perms=%lx\n", dwProtect));
if (!ReadProcessMemory(hProcess,
pbModule + inh.IMPORT_DIRECTORY.VirtualAddress,
&piid[nDlls],
nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR), &cbRead)
|| cbRead < nOldDlls * sizeof(IMAGE_IMPORT_DESCRIPTOR)) {
DETOUR_TRACE(("ReadProcessMemory(imports) failed: %lu\n", GetLastError()));
goto finish;
}
}
for (n = 0; n < nDlls; n++) {
HRESULT hrRet = StringCchCopyA((char*)pbNew + obStr, cbNew - obStr, plpDlls[n]);
if (FAILED(hrRet)) {
DETOUR_TRACE(("StringCchCopyA failed: %08lx\n", hrRet));
goto finish;
}
// After copying the string, we patch up the size "??" bits if any.
hrRet = ReplaceOptionalSizeA((char*)pbNew + obStr,
cbNew - obStr,
DETOURS_STRINGIFY(DETOURS_BITS_XX));
if (FAILED(hrRet)) {
DETOUR_TRACE(("ReplaceOptionalSizeA failed: %08lx\n", hrRet));
goto finish;
}
DWORD nOffset = obTab + (sizeof(IMAGE_THUNK_DATAXX) * (4 * n));
piid[n].OriginalFirstThunk = obBase + nOffset;
// We need 2 thunks for the import table and 2 thunks for the IAT.
// One for an ordinal import and one to mark the end of the list.
pt = ((IMAGE_THUNK_DATAXX*)(pbNew + nOffset));
pt[0].u1.Ordinal = IMAGE_ORDINAL_FLAG_XX + 1;
pt[1].u1.Ordinal = 0;
nOffset = obTab + (sizeof(IMAGE_THUNK_DATAXX) * ((4 * n) + 2));
piid[n].FirstThunk = obBase + nOffset;
pt = ((IMAGE_THUNK_DATAXX*)(pbNew + nOffset));
pt[0].u1.Ordinal = IMAGE_ORDINAL_FLAG_XX + 1;
pt[1].u1.Ordinal = 0;
piid[n].TimeDateStamp = 0;
piid[n].ForwarderChain = 0;
piid[n].Name = obBase + obStr;
obStr += PadToDword((DWORD)strlen(plpDlls[n]) + 1);
}
_Analysis_assume_(obStr <= cbNew);
#if 0
for (i = 0; i < nDlls + nOldDlls; i++) {
DETOUR_TRACE(("%8d. Look=%08x Time=%08x Fore=%08x Name=%08x Addr=%08x\n",
i,
piid[i].OriginalFirstThunk,
piid[i].TimeDateStamp,
piid[i].ForwarderChain,
piid[i].Name,
piid[i].FirstThunk));
if (piid[i].OriginalFirstThunk == 0 && piid[i].FirstThunk == 0) {
break;
}
}
#endif
if (!WriteProcessMemory(hProcess, pbNewIid, pbNew, obStr, NULL)) {
DETOUR_TRACE(("WriteProcessMemory(iid) failed: %lu\n", GetLastError()));
goto finish;
}
DETOUR_TRACE(("obBaseBef = %08lx..%08lx\n",
inh.IMPORT_DIRECTORY.VirtualAddress,
inh.IMPORT_DIRECTORY.VirtualAddress + inh.IMPORT_DIRECTORY.Size));
DETOUR_TRACE(("obBaseAft = %08lx..%08lx\n", obBase, obBase + obStr));
// In this case the file didn't have an import directory in first place,
// so we couldn't fix the missing IAT above. We still need to explicitly
// provide an IAT to prevent to loader from looking for one.
//
if (inh.IAT_DIRECTORY.VirtualAddress == 0) {
inh.IAT_DIRECTORY.VirtualAddress = obBase;
inh.IAT_DIRECTORY.Size = cbNew;
}
inh.IMPORT_DIRECTORY.VirtualAddress = obBase;
inh.IMPORT_DIRECTORY.Size = cbNew;
/////////////////////// Update the NT header for the new import directory.
//
if (!DetourVirtualProtectSameExecuteEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
PAGE_EXECUTE_READWRITE, &dwProtect)) {
DETOUR_TRACE(("VirtualProtectEx(inh) write failed: %lu\n", GetLastError()));
goto finish;
}
inh.OptionalHeader.CheckSum = 0;
if (!WriteProcessMemory(hProcess, pbModule, &idh, sizeof(idh), NULL)) {
DETOUR_TRACE(("WriteProcessMemory(idh) failed: %lu\n", GetLastError()));
goto finish;
}
DETOUR_TRACE(("WriteProcessMemory(idh:%p..%p)\n", pbModule, pbModule + sizeof(idh)));
if (!WriteProcessMemory(hProcess, pbModule + idh.e_lfanew, &inh, sizeof(inh), NULL)) {
DETOUR_TRACE(("WriteProcessMemory(inh) failed: %lu\n", GetLastError()));
goto finish;
}
DETOUR_TRACE(("WriteProcessMemory(inh:%p..%p)\n",
pbModule + idh.e_lfanew,
pbModule + idh.e_lfanew + sizeof(inh)));
if (!VirtualProtectEx(hProcess, pbModule, inh.OptionalHeader.SizeOfHeaders,
dwProtect, &dwProtect)) {
DETOUR_TRACE(("VirtualProtectEx(idh) restore failed: %lu\n", GetLastError()));
goto finish;
}
fSucceeded = TRUE;
goto finish;
}

View File

@ -21,6 +21,15 @@
#include <tchar.h> #include <tchar.h>
#include <dwmapi.h> #include <dwmapi.h>
// Includes of the game have to be here since this header is precompiled.
#include "string"
#include "d3d11.h"
#include "public/include/httplib.h"
// Game ImGui headers are here for mouse tracking.
#include "gameui/IBrowser.h"
#include "gameui/IConsole.h"
// Configuration flags to add in your imconfig.h file: // Configuration flags to add in your imconfig.h file:
//#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad support. This was meaningful before <1.81 but we now load XInput dynamically so the option is now less relevant. //#define IMGUI_IMPL_WIN32_DISABLE_GAMEPAD // Disable gamepad support. This was meaningful before <1.81 but we now load XInput dynamically so the option is now less relevant.
@ -190,6 +199,9 @@ void ImGui_ImplWin32_Shutdown()
static bool ImGui_ImplWin32_UpdateMouseCursor() static bool ImGui_ImplWin32_UpdateMouseCursor()
{ {
// These have to be here to prevent the mouse in-game from flickering when '::SetCursor(...)' is called.
if (g_pIBrowser->m_bActivate || g_pIConsole->m_bActivate)
{
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
return false; return false;
@ -219,6 +231,8 @@ static bool ImGui_ImplWin32_UpdateMouseCursor()
::SetCursor(::LoadCursor(NULL, win32_cursor)); ::SetCursor(::LoadCursor(NULL, win32_cursor));
} }
return true; return true;
}
return false;
} }
static void ImGui_ImplWin32_UpdateMousePos() static void ImGui_ImplWin32_UpdateMousePos()

View File

@ -0,0 +1,40 @@
// File: lzham_assert.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
const unsigned int LZHAM_FAIL_EXCEPTION_CODE = 256U;
void lzham_enable_fail_exceptions(bool enabled);
void lzham_assert(const char* pExp, const char* pFile, unsigned line);
void lzham_fail(const char* pExp, const char* pFile, unsigned line);
#ifdef NDEBUG
#define LZHAM_ASSERT(x) ((void)0)
#else
#define LZHAM_ASSERT(_exp) (void)( (!!(_exp)) || (lzham_assert(#_exp, __FILE__, __LINE__), 0) )
#define LZHAM_ASSERTS_ENABLED 1
#endif
#define LZHAM_VERIFY(_exp) (void)( (!!(_exp)) || (lzham_assert(#_exp, __FILE__, __LINE__), 0) )
#define LZHAM_FAIL(msg) do { lzham_fail(#msg, __FILE__, __LINE__); } while(0)
#define LZHAM_ASSERT_OPEN_RANGE(x, l, h) LZHAM_ASSERT((x >= l) && (x < h))
#define LZHAM_ASSERT_CLOSED_RANGE(x, l, h) LZHAM_ASSERT((x >= l) && (x <= h))
void lzham_trace(const char* pFmt, va_list args);
void lzham_trace(const char* pFmt, ...);
// Borrowed from boost libraries.
template <bool x> struct assume_failure;
template <> struct assume_failure<true> { enum { blah = 1 }; };
template<int x> struct assume_try { };
#define LZHAM_JOINER_FINAL(a, b) a##b
#define LZHAM_JOINER(a, b) LZHAM_JOINER_FINAL(a, b)
#define LZHAM_JOIN(a, b) LZHAM_JOINER(a, b)
#if defined(__GNUC__)
#define LZHAM_ASSUME(p) typedef assume_try < sizeof(assume_failure< (bool)(p) > ) > LZHAM_JOIN(assume_typedef, __COUNTER__) __attribute__((unused))
#else
#define LZHAM_ASSUME(p) typedef assume_try < sizeof(assume_failure< (bool)(p) > ) > LZHAM_JOIN(assume_typedef, __COUNTER__)
#endif

View File

@ -0,0 +1,13 @@
// File: lzham_checksum.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
namespace lzham
{
const uint cInitAdler32 = 1U;
uint adler32(const void* pBuf, size_t buflen, uint adler32 = cInitAdler32);
const uint cInitCRC32 = 0U;
uint crc32(uint crc, const lzham_uint8 *ptr, size_t buf_len);
} // namespace lzham

View File

@ -0,0 +1,23 @@
// File: lzham_config.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
#ifdef _DEBUG
#define LZHAM_BUILD_DEBUG
#ifndef DEBUG
#define DEBUG
#endif
#else
#define LZHAM_BUILD_RELEASE
#ifndef NDEBUG
#define NDEBUG
#endif
#ifdef DEBUG
#error DEBUG cannot be defined in LZHAM_BUILD_RELEASE
#endif
#endif
#define LZHAM_BUFFERED_PRINTF 0
#define LZHAM_PERF_SECTIONS 0

View File

@ -0,0 +1,171 @@
// File: lzham_core.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
#if defined(_MSC_VER)
#pragma warning (disable: 4127) // conditional expression is constant
#endif
#if defined(_XBOX) && !defined(LZHAM_ANSI_CPLUSPLUS)
// X360
#include <xtl.h>
#define _HAS_EXCEPTIONS 0
#define NOMINMAX
#define LZHAM_PLATFORM_X360 1
#define LZHAM_USE_WIN32_API 1
#define LZHAM_USE_WIN32_ATOMIC_FUNCTIONS 1
#define LZHAM_64BIT_POINTERS 0
#define LZHAM_CPU_HAS_64BIT_REGISTERS 1
#define LZHAM_BIG_ENDIAN_CPU 1
#define LZHAM_USE_UNALIGNED_INT_LOADS 1
#define LZHAM_RESTRICT __restrict
#define LZHAM_FORCE_INLINE __forceinline
#define LZHAM_NOTE_UNUSED(x) (void)x
#elif defined(WIN32) && !defined(LZHAM_ANSI_CPLUSPLUS)
// MSVC or MinGW, x86 or x64, Win32 API's for threading and Win32 Interlocked API's or GCC built-ins for atomic ops.
#ifdef NDEBUG
// Ensure checked iterators are disabled.
#define _SECURE_SCL 0
#define _HAS_ITERATOR_DEBUGGING 0
#endif
#ifndef _DLL
// If we're using the DLL form of the run-time libs, we're also going to be enabling exceptions because we'll be building CLR apps.
// Otherwise, we disable exceptions for a small speed boost.
//#define _HAS_EXCEPTIONS 0
#endif
#define NOMINMAX
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x500
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#define LZHAM_USE_WIN32_API 1
#if defined(__MINGW32__) || defined(__MINGW64__)
#define LZHAM_USE_GCC_ATOMIC_BUILTINS 1
#else
#define LZHAM_USE_WIN32_ATOMIC_FUNCTIONS 1
#endif
#define LZHAM_PLATFORM_PC 1
#ifdef _WIN64
#define LZHAM_PLATFORM_PC_X64 1
#define LZHAM_64BIT_POINTERS 1
#define LZHAM_CPU_HAS_64BIT_REGISTERS 1
#define LZHAM_LITTLE_ENDIAN_CPU 1
#else
#define LZHAM_PLATFORM_PC_X86 1
#define LZHAM_64BIT_POINTERS 0
#define LZHAM_CPU_HAS_64BIT_REGISTERS 0
#define LZHAM_LITTLE_ENDIAN_CPU 1
#endif
#define LZHAM_USE_UNALIGNED_INT_LOADS 1
#define LZHAM_RESTRICT __restrict
#define LZHAM_FORCE_INLINE __forceinline
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
#define LZHAM_USE_MSVC_INTRINSICS 1
#endif
#define LZHAM_NOTE_UNUSED(x) (void)x
#elif defined(__GNUC__) && !defined(LZHAM_ANSI_CPLUSPLUS)
// GCC x86 or x64, pthreads for threading and GCC built-ins for atomic ops.
#define LZHAM_PLATFORM_PC 1
#if defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__)
#define LZHAM_PLATFORM_PC_X64 1
#define LZHAM_64BIT_POINTERS 1
#define LZHAM_CPU_HAS_64BIT_REGISTERS 1
#else
#define LZHAM_PLATFORM_PC_X86 1
#define LZHAM_64BIT_POINTERS 0
#define LZHAM_CPU_HAS_64BIT_REGISTERS 0
#endif
#define LZHAM_USE_UNALIGNED_INT_LOADS 1
#define LZHAM_LITTLE_ENDIAN_CPU 1
#define LZHAM_USE_PTHREADS_API 1
#define LZHAM_USE_GCC_ATOMIC_BUILTINS 1
#define LZHAM_RESTRICT
#if defined(__clang__)
#define LZHAM_FORCE_INLINE inline
#else
#define LZHAM_FORCE_INLINE inline __attribute__((__always_inline__,__gnu_inline__))
#endif
#define LZHAM_NOTE_UNUSED(x) (void)x
#else
// Vanilla ANSI-C/C++
// No threading support, unaligned loads are NOT okay.
#if defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__)
#define LZHAM_64BIT_POINTERS 1
#define LZHAM_CPU_HAS_64BIT_REGISTERS 1
#else
#define LZHAM_64BIT_POINTERS 0
#define LZHAM_CPU_HAS_64BIT_REGISTERS 0
#endif
#define LZHAM_USE_UNALIGNED_INT_LOADS 0
#if __BIG_ENDIAN__
#define LZHAM_BIG_ENDIAN_CPU 1
#else
#define LZHAM_LITTLE_ENDIAN_CPU 1
#endif
#define LZHAM_USE_GCC_ATOMIC_BUILTINS 0
#define LZHAM_USE_WIN32_ATOMIC_FUNCTIONS 0
#define LZHAM_RESTRICT
#define LZHAM_FORCE_INLINE inline
#define LZHAM_NOTE_UNUSED(x) (void)x
#include <windows.h>
#endif
#if LZHAM_LITTLE_ENDIAN_CPU
const bool c_lzham_little_endian_platform = true;
#else
const bool c_lzham_little_endian_platform = false;
#endif
const bool c_lzham_big_endian_platform = !c_lzham_little_endian_platform;
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <malloc.h>
#include <stdarg.h>
#include <memory.h>
#include <limits.h>
#include <algorithm>
#include <errno.h>
#include "lzham.h"
#include "lzham_config.h"
#include "lzham_types.h"
#include "lzham_assert.h"
#include "lzham_platform.h"
#include "lzham_helpers.h"
#include "lzham_traits.h"
#include "lzham_mem.h"
#include "lzham_math.h"
#include "lzham_utils.h"
#include "lzham_vector.h"

View File

@ -0,0 +1,54 @@
// File: lzham_helpers.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
#define LZHAM_NO_COPY_OR_ASSIGNMENT_OP(c) c(const c&); c& operator= (const c&);
namespace lzham
{
namespace helpers
{
template<typename T> struct rel_ops
{
friend inline bool operator!=(const T& x, const T& y) { return (!(x == y)); }
friend inline bool operator> (const T& x, const T& y) { return (y < x); }
friend inline bool operator<=(const T& x, const T& y) { return (!(y < x)); }
friend inline bool operator>=(const T& x, const T& y) { return (!(x < y)); }
};
template <typename T>
inline T* construct(T* p)
{
return new (static_cast<void*>(p)) T;
}
template <typename T, typename U>
inline T* construct(T* p, const U& init)
{
return new (static_cast<void*>(p)) T(init);
}
template <typename T>
inline void construct_array(T* p, uint n);
template <typename T, typename U>
inline void construct_array(T* p, uint n, const U& init)
{
T* q = p + n;
for ( ; p != q; ++p)
new (static_cast<void*>(p)) T(init);
}
template <typename T>
inline void destruct(T* p)
{
LZHAM_NOTE_UNUSED(p);
p->~T();
}
template <typename T>
inline void destruct_array(T* p, uint n);
} // namespace helpers
} // namespace lzham

View File

@ -0,0 +1,14 @@
// File: lzham_huffman_codes.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
namespace lzham
{
//const uint cHuffmanMaxSupportedSyms = 600;
const uint cHuffmanMaxSupportedSyms = 1024;
uint get_generate_huffman_codes_table_size();
bool generate_huffman_codes(void* pContext, uint num_syms, const uint16* pFreq, uint8* pCodesizes, uint& max_code_size, uint& total_freq_ret);
} // namespace lzham

View File

@ -0,0 +1,45 @@
// File: lzham_lzbase.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
#include "../lzhamdecomp/lzham_lzdecompbase.h"
//#define LZHAM_LZVERIFY
//#define LZHAM_DISABLE_RAW_BLOCKS
namespace lzham
{
struct CLZBase : CLZDecompBase
{
uint8 m_slot_tab0[4096];
uint8 m_slot_tab1[512];
uint8 m_slot_tab2[256];
void init_slot_tabs();
inline void compute_lzx_position_slot(uint dist, uint& slot, uint& ofs)
{
uint s;
if (dist < 0x1000)
s = m_slot_tab0[dist];
else if (dist < 0x100000)
s = m_slot_tab1[dist >> 11];
else if (dist < 0x1000000)
s = m_slot_tab2[dist >> 16];
else if (dist < 0x2000000)
s = 48 + ((dist - 0x1000000) >> 23);
else if (dist < 0x4000000)
s = 50 + ((dist - 0x2000000) >> 24);
else
s = 52 + ((dist - 0x4000000) >> 25);
ofs = (dist - m_lzx_position_base[s]) & m_lzx_position_extra_mask[s];
slot = s;
LZHAM_ASSERT(s < m_num_lzx_slots);
LZHAM_ASSERT((m_lzx_position_base[slot] + ofs) == dist);
LZHAM_ASSERT(ofs < (1U << m_lzx_position_extra_bits[slot]));
}
};
} // namespace lzham

View File

@ -0,0 +1,146 @@
// File: lzham_match_accel.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
#include "lzham_lzbase.h"
#include "lzham_threading.h"
namespace lzham
{
const uint cMatchAccelMaxSupportedProbes = 128;
struct node
{
uint m_left;
uint m_right;
};
LZHAM_DEFINE_BITWISE_MOVABLE(node);
#pragma pack(push, 1)
struct dict_match
{
uint m_dist;
uint16 m_len;
inline uint get_dist() const { return m_dist & 0x7FFFFFFF; }
inline uint get_len() const { return m_len + 2; }
inline bool is_last() const { return (int)m_dist < 0; }
};
#pragma pack(pop)
LZHAM_DEFINE_BITWISE_MOVABLE(dict_match);
class search_accelerator
{
public:
search_accelerator();
// If all_matches is true, the match finder returns all found matches with no filtering.
// Otherwise, the finder will tend to return lists of matches with mostly unique lengths.
// For each length, it will discard matches with worse distances (in the coding sense).
bool init(CLZBase* pLZBase, task_pool* pPool, uint max_helper_threads, uint max_dict_size, uint max_matches, bool all_matches, uint max_probes);
void reset();
void flush();
inline uint get_max_dict_size() const { return m_max_dict_size; }
inline uint get_max_dict_size_mask() const { return m_max_dict_size_mask; }
inline uint get_cur_dict_size() const { return m_cur_dict_size; }
inline uint get_lookahead_pos() const { return m_lookahead_pos; }
inline uint get_lookahead_size() const { return m_lookahead_size; }
inline uint get_char(int delta_pos) const { return m_dict[(m_lookahead_pos + delta_pos) & m_max_dict_size_mask]; }
inline uint get_char(uint cur_dict_pos, int delta_pos) const { return m_dict[(cur_dict_pos + delta_pos) & m_max_dict_size_mask]; }
inline const uint8* get_ptr(uint pos) const { return &m_dict[pos]; }
uint get_max_helper_threads() const { return m_max_helper_threads; }
inline uint operator[](uint pos) const { return m_dict[pos]; }
uint get_max_add_bytes() const;
bool add_bytes_begin(uint num_bytes, const uint8* pBytes);
inline atomic32_t get_num_completed_helper_threads() const { return m_num_completed_helper_threads; }
void add_bytes_end();
// Returns the lookahead's raw position/size/dict_size at the time add_bytes_begin() is called.
inline uint get_fill_lookahead_pos() const { return m_fill_lookahead_pos; }
inline uint get_fill_lookahead_size() const { return m_fill_lookahead_size; }
inline uint get_fill_dict_size() const { return m_fill_dict_size; }
uint get_len2_match(uint lookahead_ofs);
dict_match* find_matches(uint lookahead_ofs, bool spin = true);
void advance_bytes(uint num_bytes);
LZHAM_FORCE_INLINE uint get_match_len(uint lookahead_ofs, int dist, uint max_match_len, uint start_match_len = 0) const
{
LZHAM_ASSERT(lookahead_ofs < m_lookahead_size);
LZHAM_ASSERT(start_match_len <= max_match_len);
LZHAM_ASSERT(max_match_len <= (get_lookahead_size() - lookahead_ofs));
const int find_dict_size = m_cur_dict_size + lookahead_ofs;
if (dist > find_dict_size)
return 0;
const uint comp_pos = static_cast<uint>((m_lookahead_pos + lookahead_ofs - dist) & m_max_dict_size_mask);
const uint lookahead_pos = (m_lookahead_pos + lookahead_ofs) & m_max_dict_size_mask;
const uint8* pComp = &m_dict[comp_pos];
const uint8* pLookahead = &m_dict[lookahead_pos];
uint match_len;
for (match_len = start_match_len; match_len < max_match_len; match_len++)
if (pComp[match_len] != pLookahead[match_len])
break;
return match_len;
}
public:
CLZBase* m_pLZBase;
task_pool* m_pTask_pool;
uint m_max_helper_threads;
uint m_max_dict_size;
uint m_max_dict_size_mask;
uint m_lookahead_pos;
uint m_lookahead_size;
uint m_cur_dict_size;
lzham::vector<uint8> m_dict;
enum { cHashSize = 65536 };
lzham::vector<uint> m_hash;
lzham::vector<node> m_nodes;
lzham::vector<dict_match> m_matches;
lzham::vector<atomic32_t> m_match_refs;
lzham::vector<uint8> m_hash_thread_index;
enum { cDigramHashSize = 4096 };
lzham::vector<uint> m_digram_hash;
lzham::vector<uint> m_digram_next;
uint m_fill_lookahead_pos;
uint m_fill_lookahead_size;
uint m_fill_dict_size;
uint m_max_probes;
uint m_max_matches;
bool m_all_matches;
volatile atomic32_t m_next_match_ref;
volatile atomic32_t m_num_completed_helper_threads;
void find_all_matches_callback(uint64 data, void* pData_ptr);
bool find_all_matches(uint num_bytes);
bool find_len2_matches();
};
} // namespace lzham

View File

@ -0,0 +1,113 @@
// File: lzham_math.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
#if defined(LZHAM_USE_MSVC_INTRINSICS) && !defined(__MINGW32__)
#include <intrin.h>
#if defined(_MSC_VER)
#pragma intrinsic(_BitScanReverse)
#endif
#endif
namespace lzham
{
namespace math
{
// Yes I know these should probably be pass by ref, not val:
// http://www.stepanovpapers.com/notes.pdf
// Just don't use them on non-simple (non built-in) types!
template<typename T> inline T minimum(T a, T b) { return (a < b) ? a : b; }
template<typename T> inline T minimum(T a, T b, T c) { return minimum(minimum(a, b), c); }
template<typename T> inline T maximum(T a, T b) { return (a > b) ? a : b; }
template<typename T> inline T maximum(T a, T b, T c) { return maximum(maximum(a, b), c); }
template<typename T> inline T clamp(T value, T low, T high) { return (value < low) ? low : ((value > high) ? high : value); }
inline bool is_power_of_2(uint32 x) { return x && ((x & (x - 1U)) == 0U); }
inline bool is_power_of_2(uint64 x) { return x && ((x & (x - 1U)) == 0U); }
template<typename T> inline T align_up_pointer(T p, uint alignment)
{
LZHAM_ASSERT(is_power_of_2(alignment));
ptr_bits_t q = reinterpret_cast<ptr_bits_t>(p);
q = (q + alignment - 1) & (~((uint_ptr)alignment - 1));
return reinterpret_cast<T>(q);
}
// From "Hackers Delight"
// val remains unchanged if it is already a power of 2.
inline uint32 next_pow2(uint32 val)
{
val--;
val |= val >> 16;
val |= val >> 8;
val |= val >> 4;
val |= val >> 2;
val |= val >> 1;
return val + 1;
}
// val remains unchanged if it is already a power of 2.
inline uint64 next_pow2(uint64 val)
{
val--;
val |= val >> 32;
val |= val >> 16;
val |= val >> 8;
val |= val >> 4;
val |= val >> 2;
val |= val >> 1;
return val + 1;
}
inline uint floor_log2i(uint v)
{
uint l = 0;
while (v > 1U)
{
v >>= 1;
l++;
}
return l;
}
inline uint ceil_log2i(uint v)
{
uint l = floor_log2i(v);
if ((l != cIntBits) && (v > (1U << l)))
l++;
return l;
}
// Returns the total number of bits needed to encode v.
// This needs to be fast - it's used heavily when determining Polar codelengths.
inline uint total_bits(uint v)
{
unsigned long l = 0;
#if defined(__MINGW32__)
if (v)
{
l = 32 -__builtin_clz(v);
}
#elif defined(LZHAM_USE_MSVC_INTRINSICS)
if (_BitScanReverse(&l, v))
{
l++;
}
#else
while (v > 0U)
{
v >>= 1;
l++;
}
#endif
return l;
}
}
} // namespace lzham

View File

@ -0,0 +1,112 @@
// File: lzham_mem.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
namespace lzham
{
void lzham_mem_init();
void* lzham_malloc(size_t size, size_t* pActual_size = NULL);
void* lzham_realloc(void* p, size_t size, size_t* pActual_size = NULL, bool movable = true);
void lzham_free(void* p);
size_t lzham_msize(void* p);
template<typename T>
inline T* lzham_new()
{
T* p = static_cast<T*>(lzham_malloc(sizeof(T)));
if (!p) return NULL;
if (LZHAM_IS_SCALAR_TYPE(T))
return p;
return helpers::construct(p);
}
template<typename T, typename A>
inline T* lzham_new(const A& init0)
{
T* p = static_cast<T*>(lzham_malloc(sizeof(T)));
if (!p) return NULL;
return new (static_cast<void*>(p)) T(init0);
}
template<typename T, typename A, typename B>
inline T* lzham_new(const A& init0, const B& init1)
{
T* p = static_cast<T*>(lzham_malloc(sizeof(T)));
if (!p) return NULL;
return new (static_cast<void*>(p)) T(init0, init1);
}
template<typename T, typename A, typename B, typename C>
inline T* lzham_new(const A& init0, const B& init1, const C& init2)
{
T* p = static_cast<T*>(lzham_malloc(sizeof(T)));
if (!p) return NULL;
return new (static_cast<void*>(p)) T(init0, init1, init2);
}
template<typename T, typename A, typename B, typename C, typename D>
inline T* lzham_new(const A& init0, const B& init1, const C& init2, const D& init3)
{
T* p = static_cast<T*>(lzham_malloc(sizeof(T)));
if (!p) return NULL;
return new (static_cast<void*>(p)) T(init0, init1, init2, init3);
}
template<typename T>
inline T* lzham_new_array(uint32 num)
{
if (!num) num = 1;
uint8* q = static_cast<uint8*>(lzham_malloc(LZHAM_MIN_ALLOC_ALIGNMENT + sizeof(T) * num));
if (!q)
return NULL;
T* p = reinterpret_cast<T*>(q + LZHAM_MIN_ALLOC_ALIGNMENT);
reinterpret_cast<uint32*>(p)[-1] = num;
reinterpret_cast<uint32*>(p)[-2] = ~num;
if (!LZHAM_IS_SCALAR_TYPE(T))
{
helpers::construct_array(p, num);
}
return p;
}
template<typename T>
inline void lzham_delete(T* p)
{
if (p)
{
if (!LZHAM_IS_SCALAR_TYPE(T))
{
helpers::destruct(p);
}
lzham_free(p);
}
}
template<typename T>
inline void lzham_delete_array(T* p)
{
if (p)
{
const uint32 num = reinterpret_cast<uint32*>(p)[-1];
const uint32 num_check = reinterpret_cast<uint32*>(p)[-2];
LZHAM_ASSERT(num && (num == ~num_check));
if (num == ~num_check)
{
if (!LZHAM_IS_SCALAR_TYPE(T))
{
helpers::destruct_array(p, num);
}
lzham_free(reinterpret_cast<uint8*>(p) - LZHAM_MIN_ALLOC_ALIGNMENT);
}
}
}
void lzham_print_mem_stats();
} // namespace lzham

View File

@ -0,0 +1,97 @@
// File: lzham_task_pool_null.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
namespace lzham
{
class semaphore
{
LZHAM_NO_COPY_OR_ASSIGNMENT_OP(semaphore);
public:
inline semaphore(long initialCount = 0, long maximumCount = 1, const char* pName = NULL)
{
initialCount, maximumCount, pName;
}
inline ~semaphore()
{
}
inline void release(long releaseCount = 1, long *pPreviousCount = NULL)
{
releaseCount, pPreviousCount;
}
inline bool wait(uint32 milliseconds = UINT32_MAX)
{
milliseconds;
return true;
}
};
class task_pool
{
public:
inline task_pool() { }
inline task_pool(uint num_threads) { num_threads; }
inline ~task_pool() { }
inline bool init(uint num_threads) { num_threads; return true; }
inline void deinit();
inline uint get_num_threads() const { return 0; }
inline uint get_num_outstanding_tasks() const { return 0; }
// C-style task callback
typedef void (*task_callback_func)(uint64 data, void* pData_ptr);
inline bool queue_task(task_callback_func pFunc, uint64 data = 0, void* pData_ptr = NULL)
{
pFunc(data, pData_ptr);
return true;
}
class executable_task
{
public:
virtual void execute_task(uint64 data, void* pData_ptr) = 0;
};
// It's the caller's responsibility to delete pObj within the execute_task() method, if needed!
inline bool queue_task(executable_task* pObj, uint64 data = 0, void* pData_ptr = NULL)
{
pObj->execute_task(data, pData_ptr);
return true;
}
template<typename S, typename T>
inline bool queue_object_task(S* pObject, T pObject_method, uint64 data = 0, void* pData_ptr = NULL)
{
(pObject->*pObject_method)(data, pData_ptr);
return true;
}
template<typename S, typename T>
inline bool queue_multiple_object_tasks(S* pObject, T pObject_method, uint64 first_data, uint num_tasks, void* pData_ptr = NULL)
{
for (uint i = 0; i < num_tasks; i++)
{
(pObject->*pObject_method)(first_data + i, pData_ptr);
}
return true;
}
void join() { }
};
inline void lzham_sleep(unsigned int milliseconds)
{
milliseconds;
}
inline uint lzham_get_max_helper_threads()
{
return 0;
}
} // namespace lzham

View File

@ -0,0 +1,284 @@
// File: lzham_platform.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
bool lzham_is_debugger_present(void);
void lzham_debug_break(void);
void lzham_output_debug_string(const char* p);
// actually in lzham_assert.cpp
void lzham_assert(const char* pExp, const char* pFile, unsigned line);
void lzham_fail(const char* pExp, const char* pFile, unsigned line);
#ifdef WIN32
#define LZHAM_BREAKPOINT DebuggerBreak();
#define LZHAM_BUILTIN_EXPECT(c, v) c
#elif defined(__GNUC__)
#define LZHAM_BREAKPOINT asm("int $3");
#define LZHAM_BUILTIN_EXPECT(c, v) __builtin_expect(c, v)
#else
#define LZHAM_BREAKPOINT
#define LZHAM_BUILTIN_EXPECT(c, v) c
#endif
#if defined(__GNUC__) && LZHAM_PLATFORM_PC
extern __inline__ __attribute__((__always_inline__,__gnu_inline__)) void lzham_yield_processor()
{
__asm__ __volatile__("pause");
}
#elif LZHAM_PLATFORM_X360
#define lzham_yield_processor() \
YieldProcessor(); \
__asm { or r0, r0, r0 } \
YieldProcessor(); \
__asm { or r1, r1, r1 } \
YieldProcessor(); \
__asm { or r0, r0, r0 } \
YieldProcessor(); \
__asm { or r1, r1, r1 } \
YieldProcessor(); \
__asm { or r0, r0, r0 } \
YieldProcessor(); \
__asm { or r1, r1, r1 } \
YieldProcessor(); \
__asm { or r0, r0, r0 } \
YieldProcessor(); \
__asm { or r1, r1, r1 }
#else
LZHAM_FORCE_INLINE void lzham_yield_processor()
{
#if LZHAM_USE_MSVC_INTRINSICS
#if LZHAM_PLATFORM_PC_X64
_mm_pause();
#else
YieldProcessor();
#endif
#else
// No implementation
#endif
}
#endif
#ifndef _MSC_VER
int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...);
int vsprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, va_list args);
#endif
#if LZHAM_PLATFORM_X360
#define LZHAM_MEMORY_EXPORT_BARRIER MemoryBarrier();
#else
// Barriers shouldn't be necessary on x86/x64.
// TODO: Should use __sync_synchronize() on other platforms that support GCC.
#define LZHAM_MEMORY_EXPORT_BARRIER
#endif
#if LZHAM_PLATFORM_X360
#define LZHAM_MEMORY_IMPORT_BARRIER MemoryBarrier();
#else
// Barriers shouldn't be necessary on x86/x64.
// TODO: Should use __sync_synchronize() on other platforms that support GCC.
#define LZHAM_MEMORY_IMPORT_BARRIER
#endif
// Note: It's very important that LZHAM_READ_BIG_ENDIAN_UINT32() is fast on the target platform.
// This is used to read every DWORD from the input stream.
#if LZHAM_USE_UNALIGNED_INT_LOADS
#if LZHAM_BIG_ENDIAN_CPU
#define LZHAM_READ_BIG_ENDIAN_UINT32(p) *reinterpret_cast<const uint32*>(p)
#else
#if defined(LZHAM_USE_MSVC_INTRINSICS)
#define LZHAM_READ_BIG_ENDIAN_UINT32(p) _byteswap_ulong(*reinterpret_cast<const uint32*>(p))
#elif defined(__GNUC__)
#define LZHAM_READ_BIG_ENDIAN_UINT32(p) __builtin_bswap32(*reinterpret_cast<const uint32*>(p))
#else
#define LZHAM_READ_BIG_ENDIAN_UINT32(p) utils::swap32(*reinterpret_cast<const uint32*>(p))
#endif
#endif
#else
#define LZHAM_READ_BIG_ENDIAN_UINT32(p) ((reinterpret_cast<const uint8*>(p)[0] << 24) | (reinterpret_cast<const uint8*>(p)[1] << 16) | (reinterpret_cast<const uint8*>(p)[2] << 8) | (reinterpret_cast<const uint8*>(p)[3]))
#endif
#if LZHAM_USE_WIN32_ATOMIC_FUNCTIONS
extern "C" __int64 _InterlockedCompareExchange64(__int64 volatile * Destination, __int64 Exchange, __int64 Comperand);
#if defined(_MSC_VER)
#pragma intrinsic(_InterlockedCompareExchange64)
#endif
#endif // LZHAM_USE_WIN32_ATOMIC_FUNCTIONS
namespace lzham
{
#if LZHAM_USE_WIN32_ATOMIC_FUNCTIONS
typedef LONG atomic32_t;
typedef LONGLONG atomic64_t;
// Returns the original value.
inline atomic32_t atomic_compare_exchange32(atomic32_t volatile *pDest, atomic32_t exchange, atomic32_t comparand)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return InterlockedCompareExchange(pDest, exchange, comparand);
}
// Returns the original value.
inline atomic64_t atomic_compare_exchange64(atomic64_t volatile *pDest, atomic64_t exchange, atomic64_t comparand)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 7) == 0);
return _InterlockedCompareExchange64(pDest, exchange, comparand);
}
// Returns the resulting incremented value.
inline atomic32_t atomic_increment32(atomic32_t volatile *pDest)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return InterlockedIncrement(pDest);
}
// Returns the resulting decremented value.
inline atomic32_t atomic_decrement32(atomic32_t volatile *pDest)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return InterlockedDecrement(pDest);
}
// Returns the original value.
inline atomic32_t atomic_exchange32(atomic32_t volatile *pDest, atomic32_t val)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return InterlockedExchange(pDest, val);
}
// Returns the resulting value.
inline atomic32_t atomic_add32(atomic32_t volatile *pDest, atomic32_t val)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return InterlockedExchangeAdd(pDest, val) + val;
}
// Returns the original value.
inline atomic32_t atomic_exchange_add(atomic32_t volatile *pDest, atomic32_t val)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return InterlockedExchangeAdd(pDest, val);
}
#elif LZHAM_USE_GCC_ATOMIC_BUILTINS
typedef long atomic32_t;
typedef long long atomic64_t;
// Returns the original value.
inline atomic32_t atomic_compare_exchange32(atomic32_t volatile *pDest, atomic32_t exchange, atomic32_t comparand)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return __sync_val_compare_and_swap(pDest, comparand, exchange);
}
// Returns the original value.
inline atomic64_t atomic_compare_exchange64(atomic64_t volatile *pDest, atomic64_t exchange, atomic64_t comparand)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 7) == 0);
return __sync_val_compare_and_swap(pDest, comparand, exchange);
}
// Returns the resulting incremented value.
inline atomic32_t atomic_increment32(atomic32_t volatile *pDest)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return __sync_add_and_fetch(pDest, 1);
}
// Returns the resulting decremented value.
inline atomic32_t atomic_decrement32(atomic32_t volatile *pDest)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return __sync_sub_and_fetch(pDest, 1);
}
// Returns the original value.
inline atomic32_t atomic_exchange32(atomic32_t volatile *pDest, atomic32_t val)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return __sync_lock_test_and_set(pDest, val);
}
// Returns the resulting value.
inline atomic32_t atomic_add32(atomic32_t volatile *pDest, atomic32_t val)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return __sync_add_and_fetch(pDest, val);
}
// Returns the original value.
inline atomic32_t atomic_exchange_add(atomic32_t volatile *pDest, atomic32_t val)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return __sync_fetch_and_add(pDest, val);
}
#else
#define LZHAM_NO_ATOMICS 1
// Atomic ops not supported - but try to do something reasonable. Assumes no threading at all.
typedef long atomic32_t;
typedef long long atomic64_t;
inline atomic32_t atomic_compare_exchange32(atomic32_t volatile *pDest, atomic32_t exchange, atomic32_t comparand)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
atomic32_t cur = *pDest;
if (cur == comparand)
*pDest = exchange;
return cur;
}
inline atomic64_t atomic_compare_exchange64(atomic64_t volatile *pDest, atomic64_t exchange, atomic64_t comparand)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 7) == 0);
atomic64_t cur = *pDest;
if (cur == comparand)
*pDest = exchange;
return cur;
}
inline atomic32_t atomic_increment32(atomic32_t volatile *pDest)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return (*pDest += 1);
}
inline atomic32_t atomic_decrement32(atomic32_t volatile *pDest)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return (*pDest -= 1);
}
inline atomic32_t atomic_exchange32(atomic32_t volatile *pDest, atomic32_t val)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
atomic32_t cur = *pDest;
*pDest = val;
return cur;
}
inline atomic32_t atomic_add32(atomic32_t volatile *pDest, atomic32_t val)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
return (*pDest += val);
}
inline atomic32_t atomic_exchange_add(atomic32_t volatile *pDest, atomic32_t val)
{
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(pDest) & 3) == 0);
atomic32_t cur = *pDest;
*pDest += val;
return cur;
}
#endif
#if LZHAM_BUFFERED_PRINTF
void lzham_buffered_printf(const char *format, ...);
void lzham_flush_buffered_printf();
#else
inline void lzham_buffered_printf(const char *format, ...) { (void)format; }
inline void lzham_flush_buffered_printf() { }
#endif
} // namespace lzham

View File

@ -0,0 +1,14 @@
// File: lzham_polar_codes.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
namespace lzham
{
//const uint cPolarMaxSupportedSyms = 600;
const uint cPolarMaxSupportedSyms = 1024;
uint get_generate_polar_codes_table_size();
bool generate_polar_codes(void* pContext, uint num_syms, const uint16* pFreq, uint8* pCodesizes, uint& max_code_size, uint& total_freq_ret);
} // namespace lzham

View File

@ -0,0 +1,144 @@
// File: lzham_prefix_coding.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
namespace lzham
{
namespace prefix_coding
{
const uint cMaxExpectedCodeSize = 16;
const uint cMaxSupportedSyms = 1024;
const uint cMaxTableBits = 11;
bool limit_max_code_size(uint num_syms, uint8* pCodesizes, uint max_code_size);
bool generate_codes(uint num_syms, const uint8* pCodesizes, uint16* pCodes);
class decoder_tables
{
public:
inline decoder_tables() :
m_table_shift(0), m_table_max_code(0), m_decode_start_code_size(0), m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL)
{
}
inline decoder_tables(const decoder_tables& other) :
m_table_shift(0), m_table_max_code(0), m_decode_start_code_size(0), m_cur_lookup_size(0), m_lookup(NULL), m_cur_sorted_symbol_order_size(0), m_sorted_symbol_order(NULL)
{
*this = other;
}
inline decoder_tables& operator= (const decoder_tables& rhs)
{
assign(rhs);
return *this;
}
inline bool assign(const decoder_tables& rhs)
{
if (this == &rhs)
return true;
uint32* pCur_lookup = m_lookup;
uint16* pCur_sorted_symbol_order = m_sorted_symbol_order;
memcpy(this, &rhs, sizeof(*this));
if ((pCur_lookup) && (pCur_sorted_symbol_order) && (rhs.m_cur_lookup_size == m_cur_lookup_size) && (rhs.m_cur_sorted_symbol_order_size == m_cur_sorted_symbol_order_size))
{
m_lookup = pCur_lookup;
m_sorted_symbol_order = pCur_sorted_symbol_order;
memcpy(m_lookup, rhs.m_lookup, sizeof(m_lookup[0]) * m_cur_lookup_size);
memcpy(m_sorted_symbol_order, rhs.m_sorted_symbol_order, sizeof(m_sorted_symbol_order[0]) * m_cur_sorted_symbol_order_size);
}
else
{
lzham_delete_array(pCur_lookup);
m_lookup = NULL;
if (rhs.m_lookup)
{
m_lookup = lzham_new_array<uint32>(m_cur_lookup_size);
if (!m_lookup)
return false;
memcpy(m_lookup, rhs.m_lookup, sizeof(m_lookup[0]) * m_cur_lookup_size);
}
lzham_delete_array(pCur_sorted_symbol_order);
m_sorted_symbol_order = NULL;
if (rhs.m_sorted_symbol_order)
{
m_sorted_symbol_order = lzham_new_array<uint16>(m_cur_sorted_symbol_order_size);
if (!m_sorted_symbol_order)
return false;
memcpy(m_sorted_symbol_order, rhs.m_sorted_symbol_order, sizeof(m_sorted_symbol_order[0]) * m_cur_sorted_symbol_order_size);
}
}
return true;
}
inline void clear()
{
if (m_lookup)
{
lzham_delete_array(m_lookup);
m_lookup = 0;
m_cur_lookup_size = 0;
}
if (m_sorted_symbol_order)
{
lzham_delete_array(m_sorted_symbol_order);
m_sorted_symbol_order = NULL;
m_cur_sorted_symbol_order_size = 0;
}
}
inline ~decoder_tables()
{
if (m_lookup)
lzham_delete_array(m_lookup);
if (m_sorted_symbol_order)
lzham_delete_array(m_sorted_symbol_order);
}
// DO NOT use any complex classes here - it is bitwise copied.
uint m_num_syms;
uint m_total_used_syms;
uint m_table_bits;
uint m_table_shift;
uint m_table_max_code;
uint m_decode_start_code_size;
uint8 m_min_code_size;
uint8 m_max_code_size;
uint m_max_codes[cMaxExpectedCodeSize + 1];
int m_val_ptrs[cMaxExpectedCodeSize + 1];
uint m_cur_lookup_size;
uint32* m_lookup;
uint m_cur_sorted_symbol_order_size;
uint16* m_sorted_symbol_order;
inline uint get_unshifted_max_code(uint len) const
{
LZHAM_ASSERT( (len >= 1) && (len <= cMaxExpectedCodeSize) );
uint k = m_max_codes[len - 1];
if (!k)
return UINT_MAX;
return (k - 1) >> (16 - len);
}
};
bool generate_decoder_tables(uint num_syms, const uint8* pCodesizes, decoder_tables* pTables, uint table_bits);
} // namespace prefix_coding
} // namespace lzham

View File

@ -0,0 +1,383 @@
// File: lzham_task_pool_pthreads.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
#if LZHAM_USE_PTHREADS_API
#if LZHAM_NO_ATOMICS
#error No atomic operations defined in lzham_platform.h!
#endif
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
namespace lzham
{
class semaphore
{
LZHAM_NO_COPY_OR_ASSIGNMENT_OP(semaphore);
public:
inline semaphore(long initialCount = 0, long maximumCount = 1, const char* pName = NULL)
{
LZHAM_NOTE_UNUSED(maximumCount), LZHAM_NOTE_UNUSED(pName);
LZHAM_ASSERT(maximumCount >= initialCount);
if (sem_init(&m_sem, 0, initialCount))
{
LZHAM_FAIL("semaphore: sem_init() failed");
}
}
inline ~semaphore()
{
sem_destroy(&m_sem);
}
inline void release(long releaseCount = 1)
{
LZHAM_ASSERT(releaseCount >= 1);
int status = 0;
#ifdef WIN32
if (1 == releaseCount)
status = sem_post(&m_sem);
else
status = sem_post_multiple(&m_sem, releaseCount);
#else
while (releaseCount > 0)
{
status = sem_post(&m_sem);
if (status)
break;
releaseCount--;
}
#endif
if (status)
{
LZHAM_FAIL("semaphore: sem_post() or sem_post_multiple() failed");
}
}
inline bool wait(uint32 milliseconds = UINT32_MAX)
{
int status;
if (milliseconds == UINT32_MAX)
{
status = sem_wait(&m_sem);
}
else
{
struct timespec interval;
interval.tv_sec = milliseconds / 1000;
interval.tv_nsec = (milliseconds % 1000) * 1000000L;
status = sem_timedwait(&m_sem, &interval);
}
if (status)
{
if (errno != ETIMEDOUT)
{
LZHAM_FAIL("semaphore: sem_wait() or sem_timedwait() failed");
}
return false;
}
return true;
}
private:
sem_t m_sem;
};
class spinlock
{
public:
inline spinlock()
{
if (pthread_spin_init(&m_spinlock, 0))
{
LZHAM_FAIL("spinlock: pthread_spin_init() failed");
}
}
inline ~spinlock()
{
pthread_spin_destroy(&m_spinlock);
}
inline void lock()
{
if (pthread_spin_lock(&m_spinlock))
{
LZHAM_FAIL("spinlock: pthread_spin_lock() failed");
}
}
inline void unlock()
{
if (pthread_spin_unlock(&m_spinlock))
{
LZHAM_FAIL("spinlock: pthread_spin_unlock() failed");
}
}
private:
pthread_spinlock_t m_spinlock;
};
template<typename T, uint cMaxSize>
class tsstack
{
public:
inline tsstack() : m_top(0)
{
}
inline ~tsstack()
{
}
inline void clear()
{
m_spinlock.lock();
m_top = 0;
m_spinlock.unlock();
}
inline bool try_push(const T& obj)
{
bool result = false;
m_spinlock.lock();
if (m_top < (int)cMaxSize)
{
m_stack[m_top++] = obj;
result = true;
}
m_spinlock.unlock();
return result;
}
inline bool pop(T& obj)
{
bool result = false;
m_spinlock.lock();
if (m_top > 0)
{
obj = m_stack[--m_top];
result = true;
}
m_spinlock.unlock();
return result;
}
private:
spinlock m_spinlock;
T m_stack[cMaxSize];
int m_top;
};
class task_pool
{
public:
task_pool();
task_pool(uint num_threads);
~task_pool();
enum { cMaxThreads = LZHAM_MAX_HELPER_THREADS };
bool init(uint num_threads);
void deinit();
inline uint get_num_threads() const { return m_num_threads; }
inline uint get_num_outstanding_tasks() const { return m_num_outstanding_tasks; }
// C-style task callback
typedef void (*task_callback_func)(uint64 data, void* pData_ptr);
bool queue_task(task_callback_func pFunc, uint64 data = 0, void* pData_ptr = NULL);
class executable_task
{
public:
virtual void execute_task(uint64 data, void* pData_ptr) = 0;
};
// It's the caller's responsibility to delete pObj within the execute_task() method, if needed!
bool queue_task(executable_task* pObj, uint64 data = 0, void* pData_ptr = NULL);
template<typename S, typename T>
inline bool queue_object_task(S* pObject, T pObject_method, uint64 data = 0, void* pData_ptr = NULL);
template<typename S, typename T>
inline bool queue_multiple_object_tasks(S* pObject, T pObject_method, uint64 first_data, uint num_tasks, void* pData_ptr = NULL);
void join();
private:
struct task
{
inline task() : m_data(0), m_pData_ptr(NULL), m_pObj(NULL), m_flags(0) { }
uint64 m_data;
void* m_pData_ptr;
union
{
task_callback_func m_callback;
executable_task* m_pObj;
};
uint m_flags;
};
tsstack<task, cMaxThreads> m_task_stack;
uint m_num_threads;
pthread_t m_threads[cMaxThreads];
semaphore m_tasks_available;
enum task_flags
{
cTaskFlagObject = 1
};
volatile atomic32_t m_num_outstanding_tasks;
volatile atomic32_t m_exit_flag;
void process_task(task& tsk);
static void* thread_func(void *pContext);
};
enum object_task_flags
{
cObjectTaskFlagDefault = 0,
cObjectTaskFlagDeleteAfterExecution = 1
};
template<typename T>
class object_task : public task_pool::executable_task
{
public:
object_task(uint flags = cObjectTaskFlagDefault) :
m_pObject(NULL),
m_pMethod(NULL),
m_flags(flags)
{
}
typedef void (T::*object_method_ptr)(uint64 data, void* pData_ptr);
object_task(T* pObject, object_method_ptr pMethod, uint flags = cObjectTaskFlagDefault) :
m_pObject(pObject),
m_pMethod(pMethod),
m_flags(flags)
{
LZHAM_ASSERT(pObject && pMethod);
}
void init(T* pObject, object_method_ptr pMethod, uint flags = cObjectTaskFlagDefault)
{
LZHAM_ASSERT(pObject && pMethod);
m_pObject = pObject;
m_pMethod = pMethod;
m_flags = flags;
}
T* get_object() const { return m_pObject; }
object_method_ptr get_method() const { return m_pMethod; }
virtual void execute_task(uint64 data, void* pData_ptr)
{
(m_pObject->*m_pMethod)(data, pData_ptr);
if (m_flags & cObjectTaskFlagDeleteAfterExecution)
lzham_delete(this);
}
protected:
T* m_pObject;
object_method_ptr m_pMethod;
uint m_flags;
};
template<typename S, typename T>
inline bool task_pool::queue_object_task(S* pObject, T pObject_method, uint64 data, void* pData_ptr)
{
object_task<S> *pTask = lzham_new< object_task<S> >(pObject, pObject_method, cObjectTaskFlagDeleteAfterExecution);
if (!pTask)
return false;
return queue_task(pTask, data, pData_ptr);
}
template<typename S, typename T>
inline bool task_pool::queue_multiple_object_tasks(S* pObject, T pObject_method, uint64 first_data, uint num_tasks, void* pData_ptr)
{
LZHAM_ASSERT(m_num_threads);
LZHAM_ASSERT(pObject);
LZHAM_ASSERT(num_tasks);
if (!num_tasks)
return true;
bool status = true;
uint i;
for (i = 0; i < num_tasks; i++)
{
task tsk;
tsk.m_pObj = lzham_new< object_task<S> >(pObject, pObject_method, cObjectTaskFlagDeleteAfterExecution);
if (!tsk.m_pObj)
{
status = false;
break;
}
tsk.m_data = first_data + i;
tsk.m_pData_ptr = pData_ptr;
tsk.m_flags = cTaskFlagObject;
if (!m_task_stack.try_push(tsk))
{
status = false;
break;
}
}
if (i)
{
atomic_add32(&m_num_outstanding_tasks, i);
m_tasks_available.release(i);
}
return status;
}
inline void lzham_sleep(unsigned int milliseconds)
{
#ifdef WIN32
struct timespec interval;
interval.tv_sec = milliseconds / 1000;
interval.tv_nsec = (milliseconds % 1000) * 1000000L;
pthread_delay_np(&interval);
#else
while (milliseconds)
{
int msecs_to_sleep = LZHAM_MIN(milliseconds, 1000);
usleep(msecs_to_sleep * 1000);
milliseconds -= msecs_to_sleep;
}
#endif
}
// TODO: Implement
uint lzham_get_max_helper_threads();
} // namespace lzham
#endif // LZHAM_USE_PTHREADS_API

View File

@ -0,0 +1,556 @@
// File: lzham_symbol_codec.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
#include "lzham_prefix_coding.h"
namespace lzham
{
class symbol_codec;
class adaptive_arith_data_model;
const uint cSymbolCodecArithMinLen = 0x01000000U;
const uint cSymbolCodecArithMaxLen = 0xFFFFFFFFU;
const uint cSymbolCodecArithProbBits = 11;
const uint cSymbolCodecArithProbScale = 1 << cSymbolCodecArithProbBits;
const uint cSymbolCodecArithProbHalfScale = 1 << (cSymbolCodecArithProbBits - 1);
const uint cSymbolCodecArithProbMoveBits = 5;
typedef uint64 bit_cost_t;
const uint32 cBitCostScaleShift = 24;
const uint32 cBitCostScale = (1U << cBitCostScaleShift);
const bit_cost_t cBitCostMax = UINT64_MAX;
inline bit_cost_t convert_to_scaled_bitcost(uint bits) { LZHAM_ASSERT(bits <= 255); uint32 scaled_bits = bits << cBitCostScaleShift; return static_cast<bit_cost_t>(scaled_bits); }
extern uint32 g_prob_cost[cSymbolCodecArithProbScale];
class raw_quasi_adaptive_huffman_data_model
{
public:
raw_quasi_adaptive_huffman_data_model(bool encoding = true, uint total_syms = 0, bool fast_encoding = false, bool use_polar_codes = false);
raw_quasi_adaptive_huffman_data_model(const raw_quasi_adaptive_huffman_data_model& other);
~raw_quasi_adaptive_huffman_data_model();
bool assign(const raw_quasi_adaptive_huffman_data_model& rhs);
raw_quasi_adaptive_huffman_data_model& operator= (const raw_quasi_adaptive_huffman_data_model& rhs);
void clear();
bool init(bool encoding, uint total_syms, bool fast_encoding, bool use_polar_codes, const uint16 *pInitial_sym_freq = NULL);
bool reset();
inline uint get_total_syms() const { return m_total_syms; }
void rescale();
void reset_update_rate();
bool update(uint sym);
inline bit_cost_t get_cost(uint sym) const { return convert_to_scaled_bitcost(m_code_sizes[sym]); }
public:
lzham::vector<uint16> m_initial_sym_freq;
lzham::vector<uint16> m_sym_freq;
lzham::vector<uint16> m_codes;
lzham::vector<uint8> m_code_sizes;
prefix_coding::decoder_tables* m_pDecode_tables;
uint m_total_syms;
uint m_max_cycle;
uint m_update_cycle;
uint m_symbols_until_update;
uint m_total_count;
uint8 m_decoder_table_bits;
bool m_encoding;
bool m_fast_updating;
bool m_use_polar_codes;
bool update();
friend class symbol_codec;
};
struct quasi_adaptive_huffman_data_model : public raw_quasi_adaptive_huffman_data_model
{
#if LZHAM_64BIT_POINTERS
// Ensures sizeof(quasi_adaptive_huffman_data_model) is 128 bytes on x64 (it's 64 on x86).
char m_unused_alignment[128 - sizeof(raw_quasi_adaptive_huffman_data_model)];
#endif
};
class adaptive_bit_model
{
public:
adaptive_bit_model();
adaptive_bit_model(float prob0);
adaptive_bit_model(const adaptive_bit_model& other);
inline adaptive_bit_model& operator= (const adaptive_bit_model& rhs) { m_bit_0_prob = rhs.m_bit_0_prob; return *this; }
inline void clear() { m_bit_0_prob = 1U << (cSymbolCodecArithProbBits - 1); }
void set_probability_0(float prob0);
inline void update(uint bit)
{
if (!bit)
m_bit_0_prob += ((cSymbolCodecArithProbScale - m_bit_0_prob) >> cSymbolCodecArithProbMoveBits);
else
m_bit_0_prob -= (m_bit_0_prob >> cSymbolCodecArithProbMoveBits);
LZHAM_ASSERT(m_bit_0_prob >= 1);
LZHAM_ASSERT(m_bit_0_prob < cSymbolCodecArithProbScale);
}
inline bit_cost_t get_cost(uint bit) const { return g_prob_cost[bit ? (cSymbolCodecArithProbScale - m_bit_0_prob) : m_bit_0_prob]; }
public:
uint16 m_bit_0_prob;
friend class symbol_codec;
friend class adaptive_arith_data_model;
};
// This class is not actually used by LZHAM - it's only here for comparison/experimental purposes.
class adaptive_arith_data_model
{
public:
adaptive_arith_data_model(bool encoding = true, uint total_syms = 0);
adaptive_arith_data_model(const adaptive_arith_data_model& other);
~adaptive_arith_data_model();
adaptive_arith_data_model& operator= (const adaptive_arith_data_model& rhs);
void clear();
bool init(bool encoding, uint total_syms);
bool init(bool encoding, uint total_syms, bool fast_encoding, bool use_polar_codes = false) { LZHAM_NOTE_UNUSED(fast_encoding), LZHAM_NOTE_UNUSED(use_polar_codes); return init(encoding, total_syms); }
void reset();
void reset_update_rate();
bool update(uint sym);
uint get_total_syms() const { return m_total_syms; }
bit_cost_t get_cost(uint sym) const;
public:
uint m_total_syms;
typedef lzham::vector<adaptive_bit_model> adaptive_bit_model_vector;
adaptive_bit_model_vector m_probs;
friend class symbol_codec;
};
#if LZHAM_CPU_HAS_64BIT_REGISTERS
#define LZHAM_SYMBOL_CODEC_USE_64_BIT_BUFFER 1
#else
#define LZHAM_SYMBOL_CODEC_USE_64_BIT_BUFFER 0
#endif
class symbol_codec
{
public:
symbol_codec();
void reset();
// clear() is like reset(), except it also frees all memory.
void clear();
// Encoding
bool start_encoding(uint expected_file_size);
bool encode_bits(uint bits, uint num_bits);
bool encode_arith_init();
bool encode_align_to_byte();
bool encode(uint sym, quasi_adaptive_huffman_data_model& model);
bool encode(uint bit, adaptive_bit_model& model, bool update_model = true);
bool encode(uint sym, adaptive_arith_data_model& model);
inline uint encode_get_total_bits_written() const { return m_total_bits_written; }
bool stop_encoding(bool support_arith);
const lzham::vector<uint8>& get_encoding_buf() const { return m_output_buf; }
lzham::vector<uint8>& get_encoding_buf() { return m_output_buf; }
// Decoding
typedef void (*need_bytes_func_ptr)(size_t num_bytes_consumed, void *pPrivate_data, const uint8* &pBuf, size_t &buf_size, bool &eof_flag);
bool start_decoding(const uint8* pBuf, size_t buf_size, bool eof_flag = true, need_bytes_func_ptr pNeed_bytes_func = NULL, void *pPrivate_data = NULL);
inline void decode_set_input_buffer(const uint8* pBuf, size_t buf_size, const uint8* pBuf_next, bool eof_flag)
{
m_pDecode_buf = pBuf;
m_pDecode_buf_next = pBuf_next;
m_decode_buf_size = buf_size;
m_pDecode_buf_end = pBuf + buf_size;
m_decode_buf_eof = eof_flag;
}
inline uint64 decode_get_bytes_consumed() const { return m_pDecode_buf_next - m_pDecode_buf; }
inline uint64 decode_get_bits_remaining() const { return ((m_pDecode_buf_end - m_pDecode_buf_next) << 3) + m_bit_count; }
void start_arith_decoding();
uint decode_bits(uint num_bits);
uint decode_peek_bits(uint num_bits);
void decode_remove_bits(uint num_bits);
void decode_align_to_byte();
int decode_remove_byte_from_bit_buf();
uint decode(quasi_adaptive_huffman_data_model& model);
uint decode(adaptive_bit_model& model, bool update_model = true);
uint decode(adaptive_arith_data_model& model);
uint64 stop_decoding();
uint get_total_model_updates() const { return m_total_model_updates; }
public:
const uint8* m_pDecode_buf;
const uint8* m_pDecode_buf_next;
const uint8* m_pDecode_buf_end;
size_t m_decode_buf_size;
bool m_decode_buf_eof;
need_bytes_func_ptr m_pDecode_need_bytes_func;
void* m_pDecode_private_data;
#if LZHAM_SYMBOL_CODEC_USE_64_BIT_BUFFER
typedef uint64 bit_buf_t;
enum { cBitBufSize = 64 };
#else
typedef uint32 bit_buf_t;
enum { cBitBufSize = 32 };
#endif
bit_buf_t m_bit_buf;
int m_bit_count;
uint m_total_model_updates;
lzham::vector<uint8> m_output_buf;
lzham::vector<uint8> m_arith_output_buf;
struct output_symbol
{
uint m_bits;
enum
{
cArithSym = -1,
cAlignToByteSym = -2,
cArithInit = -3
};
int16 m_num_bits;
uint16 m_arith_prob0;
};
lzham::vector<output_symbol> m_output_syms;
uint m_total_bits_written;
uint m_arith_base;
uint m_arith_value;
uint m_arith_length;
uint m_arith_total_bits;
quasi_adaptive_huffman_data_model* m_pSaved_huff_model;
void* m_pSaved_model;
uint m_saved_node_index;
bool put_bits_init(uint expected_size);
bool record_put_bits(uint bits, uint num_bits);
void arith_propagate_carry();
bool arith_renorm_enc_interval();
void arith_start_encoding();
bool arith_stop_encoding();
bool put_bits(uint bits, uint num_bits);
bool put_bits_align_to_byte();
bool flush_bits();
bool assemble_output_buf();
uint get_bits(uint num_bits);
void remove_bits(uint num_bits);
void decode_need_bytes();
enum
{
cNull,
cEncoding,
cDecoding
} m_mode;
};
// Optional macros for faster decompression. These macros implement the symbol_codec class's decode functionality.
// This is hard to debug (and just plain ugly), but using these macros eliminate function calls, and they place the most important
// member variables on the stack so they're hopefully put in registers (avoiding horrible load hit stores on some CPU's).
// The user must define the LZHAM_DECODE_NEEDS_BYTES macro, which is invoked when the decode buffer is exhausted.
#define LZHAM_SYMBOL_CODEC_DECODE_DECLARE(codec) \
uint arith_value = 0; \
uint arith_length = 0; \
symbol_codec::bit_buf_t bit_buf = 0; \
int bit_count = 0; \
const uint8* pDecode_buf_next = NULL;
#define LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec) \
arith_value = codec.m_arith_value; \
arith_length = codec.m_arith_length; \
bit_buf = codec.m_bit_buf; \
bit_count = codec.m_bit_count; \
pDecode_buf_next = codec.m_pDecode_buf_next;
#define LZHAM_SYMBOL_CODEC_DECODE_END(codec) \
codec.m_arith_value = arith_value; \
codec.m_arith_length = arith_length; \
codec.m_bit_buf = bit_buf; \
codec.m_bit_count = bit_count; \
codec.m_pDecode_buf_next = pDecode_buf_next;
// The user must declare the LZHAM_DECODE_NEEDS_BYTES macro.
#define LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, result, num_bits) \
{ \
while (LZHAM_BUILTIN_EXPECT(bit_count < (int)(num_bits), 0)) \
{ \
uint r; \
if (LZHAM_BUILTIN_EXPECT(pDecode_buf_next == codec.m_pDecode_buf_end, 0)) \
{ \
if (LZHAM_BUILTIN_EXPECT(!codec.m_decode_buf_eof, 1)) \
{ \
LZHAM_SYMBOL_CODEC_DECODE_END(codec) \
LZHAM_DECODE_NEEDS_BYTES \
LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec) \
} \
r = 0; \
if (LZHAM_BUILTIN_EXPECT(pDecode_buf_next < codec.m_pDecode_buf_end, 1)) r = *pDecode_buf_next++; \
} \
else \
r = *pDecode_buf_next++; \
bit_count += 8; \
bit_buf |= (static_cast<symbol_codec::bit_buf_t>(r) << (symbol_codec::cBitBufSize - bit_count)); \
} \
result = (num_bits) ? static_cast<uint>(bit_buf >> (symbol_codec::cBitBufSize - (num_bits))) : 0; \
bit_buf <<= (num_bits); \
bit_count -= (num_bits); \
}
#define LZHAM_SYMBOL_CODEC_DECODE_ARITH_BIT(codec, result, model) \
{ \
adaptive_bit_model *pModel; \
pModel = &model; \
while (LZHAM_BUILTIN_EXPECT(arith_length < cSymbolCodecArithMinLen, 0)) \
{ \
uint c; codec.m_pSaved_model = pModel; \
LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, c, 8); \
pModel = static_cast<adaptive_bit_model*>(codec.m_pSaved_model); \
arith_value = (arith_value << 8) | c; \
arith_length <<= 8; \
} \
uint x = pModel->m_bit_0_prob * (arith_length >> cSymbolCodecArithProbBits); \
result = (arith_value >= x); \
if (!result) \
{ \
pModel->m_bit_0_prob += ((cSymbolCodecArithProbScale - pModel->m_bit_0_prob) >> cSymbolCodecArithProbMoveBits); \
arith_length = x; \
} \
else \
{ \
pModel->m_bit_0_prob -= (pModel->m_bit_0_prob >> cSymbolCodecArithProbMoveBits); \
arith_value -= x; \
arith_length -= x; \
} \
}
#define LZHAM_SYMBOL_CODEC_DECODE_ADAPTIVE_ARITHMETIC(codec, result, model) \
{ \
adaptive_arith_data_model *pArith_data_model; \
pArith_data_model = &model; \
uint node_index; \
node_index = 1; \
do \
{ \
while (LZHAM_BUILTIN_EXPECT(arith_length < cSymbolCodecArithMinLen, 0)) \
{ \
uint c; codec.m_saved_node_index = node_index; codec.m_pSaved_model = pArith_data_model; \
LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, c, 8); \
node_index = codec.m_saved_node_index; pArith_data_model = static_cast<adaptive_arith_data_model *>(codec.m_pSaved_model); \
arith_value = (arith_value << 8) | c; \
arith_length <<= 8; \
} \
adaptive_bit_model *pBit_model; pBit_model = &pArith_data_model->m_probs[node_index]; \
uint x = pBit_model->m_bit_0_prob * (arith_length >> cSymbolCodecArithProbBits); \
uint bit; bit = (arith_value >= x); \
if (!bit) \
{ \
pBit_model->m_bit_0_prob += ((cSymbolCodecArithProbScale - pBit_model->m_bit_0_prob) >> cSymbolCodecArithProbMoveBits); \
arith_length = x; \
} \
else \
{ \
pBit_model->m_bit_0_prob -= (pBit_model->m_bit_0_prob >> cSymbolCodecArithProbMoveBits); \
arith_value -= x; \
arith_length -= x; \
} \
node_index = (node_index << 1) + bit; \
} while (node_index < pArith_data_model->m_total_syms); \
result = node_index - pArith_data_model->m_total_syms; \
}
#if LZHAM_SYMBOL_CODEC_USE_64_BIT_BUFFER
#define LZHAM_SYMBOL_CODEC_DECODE_ADAPTIVE_HUFFMAN(codec, result, model) \
{ \
quasi_adaptive_huffman_data_model* pModel; const prefix_coding::decoder_tables* pTables; \
pModel = &model; pTables = model.m_pDecode_tables; \
if (LZHAM_BUILTIN_EXPECT(bit_count < 24, 0)) \
{ \
uint c; \
pDecode_buf_next += sizeof(uint32); \
if (LZHAM_BUILTIN_EXPECT(pDecode_buf_next >= codec.m_pDecode_buf_end, 0)) \
{ \
pDecode_buf_next -= sizeof(uint32); \
while (bit_count < 24) \
{ \
if (!codec.m_decode_buf_eof) \
{ \
codec.m_pSaved_huff_model = pModel; \
LZHAM_SYMBOL_CODEC_DECODE_END(codec) \
LZHAM_DECODE_NEEDS_BYTES \
LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec) \
pModel = codec.m_pSaved_huff_model; pTables = pModel->m_pDecode_tables; \
} \
c = 0; if (pDecode_buf_next < codec.m_pDecode_buf_end) c = *pDecode_buf_next++; \
bit_count += 8; \
bit_buf |= (static_cast<symbol_codec::bit_buf_t>(c) << (symbol_codec::cBitBufSize - bit_count)); \
} \
} \
else \
{ \
c = LZHAM_READ_BIG_ENDIAN_UINT32(pDecode_buf_next - sizeof(uint32)); \
bit_count += 32; \
bit_buf |= (static_cast<symbol_codec::bit_buf_t>(c) << (symbol_codec::cBitBufSize - bit_count)); \
} \
} \
uint k = static_cast<uint>((bit_buf >> (symbol_codec::cBitBufSize - 16)) + 1); \
uint len; \
if (LZHAM_BUILTIN_EXPECT(k <= pTables->m_table_max_code, 1)) \
{ \
uint32 t = pTables->m_lookup[bit_buf >> (symbol_codec::cBitBufSize - pTables->m_table_bits)]; \
result = t & UINT16_MAX; \
len = t >> 16; \
} \
else \
{ \
len = pTables->m_decode_start_code_size; \
for ( ; ; ) \
{ \
if (LZHAM_BUILTIN_EXPECT(k <= pTables->m_max_codes[len - 1], 0)) \
break; \
len++; \
} \
int val_ptr = pTables->m_val_ptrs[len - 1] + static_cast<int>(bit_buf >> (symbol_codec::cBitBufSize - len)); \
if (((uint)val_ptr >= pModel->m_total_syms)) val_ptr = 0; \
result = pTables->m_sorted_symbol_order[val_ptr]; \
} \
bit_buf <<= len; \
bit_count -= len; \
uint freq = pModel->m_sym_freq[result]; \
freq++; \
pModel->m_sym_freq[result] = static_cast<uint16>(freq); \
LZHAM_ASSERT(freq <= UINT16_MAX); \
if (LZHAM_BUILTIN_EXPECT(--pModel->m_symbols_until_update == 0, 0)) \
{ \
pModel->update(); \
} \
}
#else
#define LZHAM_SYMBOL_CODEC_DECODE_ADAPTIVE_HUFFMAN(codec, result, model) \
{ \
quasi_adaptive_huffman_data_model* pModel; const prefix_coding::decoder_tables* pTables; \
pModel = &model; pTables = model.m_pDecode_tables; \
while (LZHAM_BUILTIN_EXPECT(bit_count < (symbol_codec::cBitBufSize - 8), 1)) \
{ \
uint c; \
if (LZHAM_BUILTIN_EXPECT(pDecode_buf_next == codec.m_pDecode_buf_end, 0)) \
{ \
if (LZHAM_BUILTIN_EXPECT(!codec.m_decode_buf_eof, 1)) \
{ \
codec.m_pSaved_huff_model = pModel; \
LZHAM_SYMBOL_CODEC_DECODE_END(codec) \
LZHAM_DECODE_NEEDS_BYTES \
LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec) \
pModel = codec.m_pSaved_huff_model; pTables = pModel->m_pDecode_tables; \
} \
c = 0; if (LZHAM_BUILTIN_EXPECT(pDecode_buf_next < codec.m_pDecode_buf_end, 1)) c = *pDecode_buf_next++; \
} \
else \
c = *pDecode_buf_next++; \
bit_count += 8; \
bit_buf |= (static_cast<symbol_codec::bit_buf_t>(c) << (symbol_codec::cBitBufSize - bit_count)); \
} \
uint k = static_cast<uint>((bit_buf >> (symbol_codec::cBitBufSize - 16)) + 1); \
uint len; \
if (LZHAM_BUILTIN_EXPECT(k <= pTables->m_table_max_code, 1)) \
{ \
uint32 t = pTables->m_lookup[bit_buf >> (symbol_codec::cBitBufSize - pTables->m_table_bits)]; \
result = t & UINT16_MAX; \
len = t >> 16; \
} \
else \
{ \
len = pTables->m_decode_start_code_size; \
for ( ; ; ) \
{ \
if (LZHAM_BUILTIN_EXPECT(k <= pTables->m_max_codes[len - 1], 0)) \
break; \
len++; \
} \
int val_ptr = pTables->m_val_ptrs[len - 1] + static_cast<int>(bit_buf >> (symbol_codec::cBitBufSize - len)); \
if (LZHAM_BUILTIN_EXPECT(((uint)val_ptr >= pModel->m_total_syms), 0)) val_ptr = 0; \
result = pTables->m_sorted_symbol_order[val_ptr]; \
} \
bit_buf <<= len; \
bit_count -= len; \
uint freq = pModel->m_sym_freq[result]; \
freq++; \
pModel->m_sym_freq[result] = static_cast<uint16>(freq); \
LZHAM_ASSERT(freq <= UINT16_MAX); \
if (LZHAM_BUILTIN_EXPECT(--pModel->m_symbols_until_update == 0, 0)) \
{ \
pModel->update(); \
} \
}
#endif
#define LZHAM_SYMBOL_CODEC_DECODE_ALIGN_TO_BYTE(codec) if (bit_count & 7) { int dummy_result; LZHAM_NOTE_UNUSED(dummy_result); LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, dummy_result, bit_count & 7); }
#define LZHAM_SYMBOL_CODEC_DECODE_REMOVE_BYTE_FROM_BIT_BUF(codec, result) \
{ \
result = -1; \
if (bit_count >= 8) \
{ \
result = static_cast<int>(bit_buf >> (symbol_codec::cBitBufSize - 8)); \
bit_buf <<= 8; \
bit_count -= 8; \
} \
}
#define LZHAM_SYMBOL_CODEC_DECODE_ARITH_START(codec) \
{ \
for ( arith_value = 0, arith_length = 0; arith_length < 4; ++arith_length ) \
{ \
uint val; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, val, 8); \
arith_value = (arith_value << 8) | val; \
} \
arith_length = cSymbolCodecArithMaxLen; \
}
} // namespace lzham

View File

@ -0,0 +1,12 @@
// File: lzham_threading.h
// See Copyright Notice and license at the end of include/lzham.h
#if LZHAM_USE_WIN32_API
#include "lzham_win32_threading.h"
#elif LZHAM_USE_PTHREADS_API
#include "lzham_pthreads_threading.h"
#else
#include "lzham_null_threading.h"
#endif

View File

@ -0,0 +1,99 @@
// File: lzham_timer.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
namespace lzham
{
typedef unsigned long long timer_ticks;
class lzham_timer
{
public:
lzham_timer();
lzham_timer(timer_ticks start_ticks);
void start();
void start(timer_ticks start_ticks);
void stop();
double get_elapsed_secs() const;
inline double get_elapsed_ms() const { return get_elapsed_secs() * 1000.0f; }
timer_ticks get_elapsed_us() const;
static void init();
static inline timer_ticks get_ticks_per_sec() { return g_freq; }
static timer_ticks get_init_ticks();
static timer_ticks get_ticks();
static double ticks_to_secs(timer_ticks ticks);
static inline double ticks_to_ms(timer_ticks ticks) { return ticks_to_secs(ticks) * 1000.0f; }
static inline double get_secs() { return ticks_to_secs(get_ticks()); }
static inline double get_ms() { return ticks_to_ms(get_ticks()); }
private:
static timer_ticks g_init_ticks;
static timer_ticks g_freq;
static double g_inv_freq;
timer_ticks m_start_time;
timer_ticks m_stop_time;
bool m_started : 1;
bool m_stopped : 1;
};
enum var_args_t { cVarArgs };
#if LZHAM_PERF_SECTIONS
class scoped_perf_section
{
public:
inline scoped_perf_section() :
m_start_ticks(lzham_timer::get_ticks())
{
m_name[0] = '?';
m_name[1] = '\0';
}
inline scoped_perf_section(const char *pName) :
m_start_ticks(lzham_timer::get_ticks())
{
strcpy_s(m_name, pName);
lzham_buffered_printf("Thread: 0x%08X, BEGIN Time: %3.3fms, Section: %s\n", GetCurrentThreadId(), lzham_timer::ticks_to_ms(m_start_ticks), m_name);
}
inline scoped_perf_section(var_args_t, const char *pName, ...) :
m_start_ticks(lzham_timer::get_ticks())
{
va_list args;
va_start(args, pName);
vsprintf_s(m_name, sizeof(m_name), pName, args);
va_end(args);
lzham_buffered_printf("Thread: 0x%08X, BEGIN Time: %3.3fms, Section: %s\n", GetCurrentThreadId(), lzham_timer::ticks_to_ms(m_start_ticks), m_name);
}
inline ~scoped_perf_section()
{
double end_ms = lzham_timer::get_ms();
double start_ms = lzham_timer::ticks_to_ms(m_start_ticks);
lzham_buffered_printf("Thread: 0x%08X, END Time: %3.3fms, Total: %3.3fms, Section: %s\n", GetCurrentThreadId(), end_ms, end_ms - start_ms, m_name);
}
private:
char m_name[64];
timer_ticks m_start_ticks;
};
#else
class scoped_perf_section
{
public:
inline scoped_perf_section() { }
inline scoped_perf_section(const char *pName) { (void)pName; }
inline scoped_perf_section(var_args_t, const char *pName, ...) { (void)pName; }
};
#endif // LZHAM_PERF_SECTIONS
} // namespace lzham

View File

@ -0,0 +1,137 @@
// File: lzham_traits.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
namespace lzham
{
template<typename T>
struct scalar_type
{
enum { cFlag = false };
static inline void construct(T* p) { helpers::construct(p); }
static inline void construct(T* p, const T& init) { helpers::construct(p, init); }
static inline void construct_array(T* p, uint n) { helpers::construct_array(p, n); }
static inline void destruct(T* p) { helpers::destruct(p); }
static inline void destruct_array(T* p, uint n) { helpers::destruct_array(p, n); }
};
template<typename T> struct scalar_type<T*>
{
enum { cFlag = true };
static inline void construct(T** p) { memset(p, 0, sizeof(T*)); }
static inline void construct(T** p, T* init) { *p = init; }
static inline void construct_array(T** p, uint n) { memset(p, 0, sizeof(T*) * n); }
static inline void destruct(T** p) { LZHAM_NOTE_UNUSED(p); }
static inline void destruct_array(T** p, uint n) { LZHAM_NOTE_UNUSED(p); LZHAM_NOTE_UNUSED(n); }
};
#define LZHAM_DEFINE_BUILT_IN_TYPE(X) \
template<> struct scalar_type<X> { \
enum { cFlag = true }; \
static inline void construct(X* p) { memset(p, 0, sizeof(X)); } \
static inline void construct(X* p, const X& init) { memcpy(p, &init, sizeof(X)); } \
static inline void construct_array(X* p, uint n) { memset(p, 0, sizeof(X) * n); } \
static inline void destruct(X* p) { LZHAM_NOTE_UNUSED(p); } \
static inline void destruct_array(X* p, uint n) { LZHAM_NOTE_UNUSED(p); LZHAM_NOTE_UNUSED(n); } };
LZHAM_DEFINE_BUILT_IN_TYPE(bool)
LZHAM_DEFINE_BUILT_IN_TYPE(char)
LZHAM_DEFINE_BUILT_IN_TYPE(unsigned char)
LZHAM_DEFINE_BUILT_IN_TYPE(short)
LZHAM_DEFINE_BUILT_IN_TYPE(unsigned short)
LZHAM_DEFINE_BUILT_IN_TYPE(int)
LZHAM_DEFINE_BUILT_IN_TYPE(unsigned int)
LZHAM_DEFINE_BUILT_IN_TYPE(long)
LZHAM_DEFINE_BUILT_IN_TYPE(unsigned long)
LZHAM_DEFINE_BUILT_IN_TYPE(float)
LZHAM_DEFINE_BUILT_IN_TYPE(double)
LZHAM_DEFINE_BUILT_IN_TYPE(long double)
#if defined(WIN32)
LZHAM_DEFINE_BUILT_IN_TYPE(__int64)
LZHAM_DEFINE_BUILT_IN_TYPE(unsigned __int64)
#endif
#undef LZHAM_DEFINE_BUILT_IN_TYPE
// See: http://erdani.org/publications/cuj-2004-06.pdf
template<typename T>
struct bitwise_movable { enum { cFlag = false }; };
// Defines type Q as bitwise movable.
#define LZHAM_DEFINE_BITWISE_MOVABLE(Q) template<> struct bitwise_movable<Q> { enum { cFlag = true }; };
template<typename T>
struct bitwise_copyable { enum { cFlag = false }; };
// Defines type Q as bitwise copyable.
#define LZHAM_DEFINE_BITWISE_COPYABLE(Q) template<> struct bitwise_copyable<Q> { enum { cFlag = true }; };
#define LZHAM_IS_POD(T) __is_pod(T)
#define LZHAM_IS_SCALAR_TYPE(T) (scalar_type<T>::cFlag)
#define LZHAM_IS_BITWISE_COPYABLE(T) ((scalar_type<T>::cFlag) || (bitwise_copyable<T>::cFlag) || LZHAM_IS_POD(T))
#define LZHAM_IS_BITWISE_MOVABLE(T) (LZHAM_IS_BITWISE_COPYABLE(T) || (bitwise_movable<T>::cFlag))
#define LZHAM_HAS_DESTRUCTOR(T) ((!scalar_type<T>::cFlag) && (!__is_pod(T)))
// From yasli_traits.h:
// Credit goes to Boost;
// also found in the C++ Templates book by Vandevoorde and Josuttis
typedef char (&yes_t)[1];
typedef char (&no_t)[2];
template <class U> yes_t class_test(int U::*);
template <class U> no_t class_test(...);
template <class T> struct is_class
{
enum { value = (sizeof(class_test<T>(0)) == sizeof(yes_t)) };
};
template <typename T> struct is_pointer
{
enum { value = false };
};
template <typename T> struct is_pointer<T*>
{
enum { value = true };
};
LZHAM_DEFINE_BITWISE_COPYABLE(empty_type);
LZHAM_DEFINE_BITWISE_MOVABLE(empty_type);
namespace helpers
{
template <typename T>
inline void construct_array(T* p, uint n)
{
if (LZHAM_IS_SCALAR_TYPE(T))
{
memset(p, 0, sizeof(T) * n);
}
else
{
T* q = p + n;
for ( ; p != q; ++p)
new (static_cast<void*>(p)) T;
}
}
template <typename T>
inline void destruct_array(T* p, uint n)
{
if ( LZHAM_HAS_DESTRUCTOR(T) )
{
T* q = p + n;
for ( ; p != q; ++p)
p->~T();
}
}
}
} // namespace lzham

View File

@ -0,0 +1,74 @@
// File: types.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
namespace lzham
{
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned int uint32;
typedef uint32 uint;
typedef signed int int32;
#ifdef __GNUC__
typedef unsigned long long uint64;
typedef long long int64;
#else
typedef unsigned __int64 uint64;
typedef signed __int64 int64;
#endif
const uint8 UINT8_MIN = 0;
//const uint8 UINT8_MAX = 0xFFU;
const uint16 UINT16_MIN = 0;
//const uint16 UINT16_MAX = 0xFFFFU;
const uint32 UINT32_MIN = 0;
//const uint32 UINT32_MAX = 0xFFFFFFFFU;
const uint64 UINT64_MIN = 0;
//const uint64 UINT64_MAX = 0xFFFFFFFFFFFFFFFFULL; //0xFFFFFFFFFFFFFFFFui64;
//const int8 INT8_MIN = -128;
//const int8 INT8_MAX = 127;
//const int16 INT16_MIN = -32768;
//const int16 INT16_MAX = 32767;
//const int32 INT32_MIN = (-2147483647 - 1);
//const int32 INT32_MAX = 2147483647;
//const int64 INT64_MIN = (int64)0x8000000000000000ULL; //(-9223372036854775807i64 - 1);
//const int64 INT64_MAX = (int64)0x7FFFFFFFFFFFFFFFULL; //9223372036854775807i64;
#if LZHAM_64BIT_POINTERS
typedef uint64 uint_ptr;
typedef uint64 uint32_ptr;
typedef int64 signed_size_t;
typedef uint64 ptr_bits_t;
const ptr_bits_t PTR_BITS_XOR = 0xDB0DD4415C87DCF7ULL;
#else
typedef unsigned int uint_ptr;
typedef unsigned int uint32_ptr;
typedef signed int signed_size_t;
typedef uint32 ptr_bits_t;
const ptr_bits_t PTR_BITS_XOR = 0x5C87DCF7UL;
#endif
enum
{
cInvalidIndex = -1
};
const uint cIntBits = sizeof(uint) * CHAR_BIT;
template<typename T> struct int_traits { enum { cMin = INT_MIN, cMax = INT_MAX, cSigned = true }; };
template<> struct int_traits<int8> { enum { cMin = INT8_MIN, cMax = INT8_MAX, cSigned = true }; };
template<> struct int_traits<int16> { enum { cMin = INT16_MIN, cMax = INT16_MAX, cSigned = true }; };
template<> struct int_traits<int32> { enum { cMin = INT32_MIN, cMax = INT32_MAX, cSigned = true }; };
template<> struct int_traits<uint> { enum { cMin = 0, cMax = UINT_MAX, cSigned = false }; };
template<> struct int_traits<uint8> { enum { cMin = 0, cMax = UINT8_MAX, cSigned = false }; };
template<> struct int_traits<uint16> { enum { cMin = 0, cMax = UINT16_MAX, cSigned = false }; };
struct empty_type { };
} // namespace lzham

View File

@ -0,0 +1,58 @@
// File: lzham_utils.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
#define LZHAM_GET_ALIGNMENT(v) ((!sizeof(v)) ? 1 : (__alignof(v) ? __alignof(v) : sizeof(uint32)))
#define LZHAM_MIN(a, b) (((a) < (b)) ? (a) : (b))
#define LZHAM_MAX(a, b) (((a) < (b)) ? (b) : (a))
template<class T, size_t N> T decay_array_to_subtype(T (&a)[N]);
#define LZHAM_ARRAY_SIZE(X) (sizeof(X) / sizeof(decay_array_to_subtype(X)))
namespace lzham
{
namespace utils
{
template<typename T> inline void swap(T& l, T& r)
{
T temp(l);
l = r;
r = temp;
}
template<typename T> inline void zero_object(T& obj)
{
memset(&obj, 0, sizeof(obj));
}
static inline uint32 swap32(uint32 x) { return ((x << 24U) | ((x << 8U) & 0x00FF0000U) | ((x >> 8U) & 0x0000FF00U) | (x >> 24U)); }
inline uint count_leading_zeros16(uint v)
{
LZHAM_ASSERT(v < 0x10000);
uint temp;
uint n = 16;
temp = v >> 8;
if (temp) { n -= 8; v = temp; }
temp = v >> 4;
if (temp) { n -= 4; v = temp; }
temp = v >> 2;
if (temp) { n -= 2; v = temp; }
temp = v >> 1;
if (temp) { n -= 1; v = temp; }
if (v & 1) n--;
return n;
}
} // namespace utils
} // namespace lzham

View File

@ -0,0 +1,588 @@
// File: lzham_vector.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
namespace lzham
{
struct elemental_vector
{
void* m_p;
uint m_size;
uint m_capacity;
typedef void (*object_mover)(void* pDst, void* pSrc, uint num);
bool increase_capacity(uint min_new_capacity, bool grow_hint, uint element_size, object_mover pRelocate, bool nofail);
};
template<typename T>
class vector : public helpers::rel_ops< vector<T> >
{
public:
typedef T* iterator;
typedef const T* const_iterator;
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef T* pointer;
typedef const T* const_pointer;
inline vector() :
m_p(NULL),
m_size(0),
m_capacity(0)
{
}
inline vector(uint n, const T& init) :
m_p(NULL),
m_size(0),
m_capacity(0)
{
increase_capacity(n, false);
helpers::construct_array(m_p, n, init);
m_size = n;
}
inline vector(const vector& other) :
m_p(NULL),
m_size(0),
m_capacity(0)
{
increase_capacity(other.m_size, false);
m_size = other.m_size;
if (LZHAM_IS_BITWISE_COPYABLE(T))
memcpy(m_p, other.m_p, m_size * sizeof(T));
else
{
T* pDst = m_p;
const T* pSrc = other.m_p;
for (uint i = m_size; i > 0; i--)
helpers::construct(pDst++, *pSrc++);
}
}
inline explicit vector(uint size) :
m_p(NULL),
m_size(0),
m_capacity(0)
{
try_resize(size);
}
inline ~vector()
{
if (m_p)
{
scalar_type<T>::destruct_array(m_p, m_size);
lzham_free(m_p);
}
}
inline vector& operator= (const vector& other)
{
if (this == &other)
return *this;
if (m_capacity >= other.m_size)
try_resize(0);
else
{
clear();
if (!increase_capacity(other.m_size, false))
{
LZHAM_FAIL("lzham::vector operator=: Out of memory!");
return *this;
}
}
if (LZHAM_IS_BITWISE_COPYABLE(T))
memcpy(m_p, other.m_p, other.m_size * sizeof(T));
else
{
T* pDst = m_p;
const T* pSrc = other.m_p;
for (uint i = other.m_size; i > 0; i--)
helpers::construct(pDst++, *pSrc++);
}
m_size = other.m_size;
return *this;
}
inline const T* begin() const { return m_p; }
T* begin() { return m_p; }
inline const T* end() const { return m_p + m_size; }
T* end() { return m_p + m_size; }
inline bool empty() const { return !m_size; }
inline uint size() const { return m_size; }
inline uint size_in_bytes() const { return m_size * sizeof(T); }
inline uint capacity() const { return m_capacity; }
// operator[] will assert on out of range indices, but in final builds there is (and will never be) any range checking on this method.
inline const T& operator[] (uint i) const { LZHAM_ASSERT(i < m_size); return m_p[i]; }
inline T& operator[] (uint i) { LZHAM_ASSERT(i < m_size); return m_p[i]; }
// at() always includes range checking, even in final builds, unlike operator [].
// The first element is returned if the index is out of range.
inline const T& at(uint i) const { LZHAM_ASSERT(i < m_size); return (i >= m_size) ? m_p[0] : m_p[i]; }
inline T& at(uint i) { LZHAM_ASSERT(i < m_size); return (i >= m_size) ? m_p[0] : m_p[i]; }
inline const T& front() const { LZHAM_ASSERT(m_size); return m_p[0]; }
inline T& front() { LZHAM_ASSERT(m_size); return m_p[0]; }
inline const T& back() const { LZHAM_ASSERT(m_size); return m_p[m_size - 1]; }
inline T& back() { LZHAM_ASSERT(m_size); return m_p[m_size - 1]; }
inline const T* get_ptr() const { return m_p; }
inline T* get_ptr() { return m_p; }
inline void clear()
{
if (m_p)
{
scalar_type<T>::destruct_array(m_p, m_size);
lzham_free(m_p);
m_p = NULL;
m_size = 0;
m_capacity = 0;
}
}
inline void clear_no_destruction()
{
if (m_p)
{
lzham_free(m_p);
m_p = NULL;
m_size = 0;
m_capacity = 0;
}
}
inline bool try_reserve(uint new_capacity)
{
return increase_capacity(new_capacity, true, true);
}
inline bool try_resize(uint new_size, bool grow_hint = false)
{
if (m_size != new_size)
{
if (new_size < m_size)
scalar_type<T>::destruct_array(m_p + new_size, m_size - new_size);
else
{
if (new_size > m_capacity)
{
if (!increase_capacity(new_size, (new_size == (m_size + 1)) || grow_hint, true))
return false;
}
scalar_type<T>::construct_array(m_p + m_size, new_size - m_size);
}
m_size = new_size;
}
return true;
}
inline bool try_resize_no_construct(uint new_size, bool grow_hint = false)
{
if (new_size > m_capacity)
{
if (!increase_capacity(new_size, (new_size == (m_size + 1)) || grow_hint, true))
return false;
}
m_size = new_size;
return true;
}
inline T* try_enlarge(uint i)
{
uint cur_size = m_size;
if (!try_resize(cur_size + i, true))
return NULL;
return get_ptr() + cur_size;
}
inline bool try_push_back(const T& obj)
{
LZHAM_ASSERT(!m_p || (&obj < m_p) || (&obj >= (m_p + m_size)));
if (m_size >= m_capacity)
{
if (!increase_capacity(m_size + 1, true, true))
return false;
}
scalar_type<T>::construct(m_p + m_size, obj);
m_size++;
return true;
}
inline void pop_back()
{
LZHAM_ASSERT(m_size);
if (m_size)
{
m_size--;
scalar_type<T>::destruct(&m_p[m_size]);
}
}
inline bool insert(uint index, const T* p, uint n)
{
LZHAM_ASSERT(index <= m_size);
if (!n)
return true;
const uint orig_size = m_size;
if (!try_resize(m_size + n, true))
return false;
const uint num_to_move = orig_size - index;
if (num_to_move)
{
if (LZHAM_IS_BITWISE_COPYABLE(T))
memmove(m_p + index + n, m_p + index, sizeof(T) * num_to_move);
else
{
const T* pSrc = m_p + orig_size - 1;
T* pDst = const_cast<T*>(pSrc) + n;
for (uint i = 0; i < num_to_move; i++)
{
LZHAM_ASSERT((pDst - m_p) < (int)m_size);
*pDst-- = *pSrc--;
}
}
}
T* pDst = m_p + index;
if (LZHAM_IS_BITWISE_COPYABLE(T))
memcpy(pDst, p, sizeof(T) * n);
else
{
for (uint i = 0; i < n; i++)
{
LZHAM_ASSERT((pDst - m_p) < (int)m_size);
*pDst++ = *p++;
}
}
return true;
}
// push_front() isn't going to be very fast - it's only here for usability.
inline bool try_push_front(const T& obj)
{
return insert(0, &obj, 1);
}
bool append(const vector& other)
{
if (other.m_size)
return insert(m_size, &other[0], other.m_size);
return true;
}
bool append(const T* p, uint n)
{
if (n)
return insert(m_size, p, n);
return true;
}
inline void erase(uint start, uint n)
{
LZHAM_ASSERT((start + n) <= m_size);
if ((start + n) > m_size)
return;
if (!n)
return;
const uint num_to_move = m_size - (start + n);
T* pDst = m_p + start;
const T* pSrc = m_p + start + n;
if (LZHAM_IS_BITWISE_COPYABLE(T))
memmove(pDst, pSrc, num_to_move * sizeof(T));
else
{
T* pDst_end = pDst + num_to_move;
while (pDst != pDst_end)
*pDst++ = *pSrc++;
scalar_type<T>::destruct_array(pDst_end, n);
}
m_size -= n;
}
inline void erase(uint index)
{
erase(index, 1);
}
inline void erase(T* p)
{
LZHAM_ASSERT((p >= m_p) && (p < (m_p + m_size)));
erase(static_cast<uint>(p - m_p));
}
void erase_unordered(uint index)
{
LZHAM_ASSERT(index < m_size);
if ((index + 1) < m_size)
(*this)[index] = back();
pop_back();
}
inline bool operator== (const vector& rhs) const
{
if (m_size != rhs.m_size)
return false;
else if (m_size)
{
if (scalar_type<T>::cFlag)
return memcmp(m_p, rhs.m_p, sizeof(T) * m_size) == 0;
else
{
const T* pSrc = m_p;
const T* pDst = rhs.m_p;
for (uint i = m_size; i; i--)
if (!(*pSrc++ == *pDst++))
return false;
}
}
return true;
}
inline bool operator< (const vector& rhs) const
{
const uint min_size = math::minimum(m_size, rhs.m_size);
const T* pSrc = m_p;
const T* pSrc_end = m_p + min_size;
const T* pDst = rhs.m_p;
while ((pSrc < pSrc_end) && (*pSrc == *pDst))
{
pSrc++;
pDst++;
}
if (pSrc < pSrc_end)
return *pSrc < *pDst;
return m_size < rhs.m_size;
}
inline void swap(vector& other)
{
utils::swap(m_p, other.m_p);
utils::swap(m_size, other.m_size);
utils::swap(m_capacity, other.m_capacity);
}
inline void sort()
{
std::sort(begin(), end());
}
inline void unique()
{
if (!empty())
{
sort();
resize(std::unique(begin(), end()) - begin());
}
}
inline void reverse()
{
uint j = m_size >> 1;
for (uint i = 0; i < j; i++)
utils::swap(m_p[i], m_p[m_size - 1 - i]);
}
inline int find(const T& key) const
{
const T* p = m_p;
const T* p_end = m_p + m_size;
uint index = 0;
while (p != p_end)
{
if (key == *p)
return index;
p++;
index++;
}
return cInvalidIndex;
}
inline int find_sorted(const T& key) const
{
if (m_size)
{
// Uniform binary search - Knuth Algorithm 6.2.1 U, unrolled twice.
int i = ((m_size + 1) >> 1) - 1;
int m = m_size;
for ( ; ; )
{
LZHAM_ASSERT_OPEN_RANGE(i, 0, (int)m_size);
const T* pKey_i = m_p + i;
int cmp = key < *pKey_i;
if ((!cmp) && (key == *pKey_i)) return i;
m >>= 1;
if (!m) break;
cmp = -cmp;
i += (((m + 1) >> 1) ^ cmp) - cmp;
LZHAM_ASSERT_OPEN_RANGE(i, 0, (int)m_size);
pKey_i = m_p + i;
cmp = key < *pKey_i;
if ((!cmp) && (key == *pKey_i)) return i;
m >>= 1;
if (!m) break;
cmp = -cmp;
i += (((m + 1) >> 1) ^ cmp) - cmp;
}
}
return cInvalidIndex;
}
template<typename Q>
inline int find_sorted(const T& key, Q less_than) const
{
if (m_size)
{
// Uniform binary search - Knuth Algorithm 6.2.1 U, unrolled twice.
int i = ((m_size + 1) >> 1) - 1;
int m = m_size;
for ( ; ; )
{
LZHAM_ASSERT_OPEN_RANGE(i, 0, (int)m_size);
const T* pKey_i = m_p + i;
int cmp = less_than(key, *pKey_i);
if ((!cmp) && (!less_than(*pKey_i, key))) return i;
m >>= 1;
if (!m) break;
cmp = -cmp;
i += (((m + 1) >> 1) ^ cmp) - cmp;
LZHAM_ASSERT_OPEN_RANGE(i, 0, (int)m_size);
pKey_i = m_p + i;
cmp = less_than(key, *pKey_i);
if ((!cmp) && (!less_than(*pKey_i, key))) return i;
m >>= 1;
if (!m) break;
cmp = -cmp;
i += (((m + 1) >> 1) ^ cmp) - cmp;
}
}
return cInvalidIndex;
}
inline uint count_occurences(const T& key) const
{
uint c = 0;
const T* p = m_p;
const T* p_end = m_p + m_size;
while (p != p_end)
{
if (key == *p)
c++;
p++;
}
return c;
}
inline void set_all(const T& o)
{
if ((sizeof(T) == 1) && (scalar_type<T>::cFlag))
memset(m_p, *reinterpret_cast<const uint8*>(&o), m_size);
else
{
T* pDst = m_p;
T* pDst_end = pDst + m_size;
while (pDst != pDst_end)
*pDst++ = o;
}
}
private:
T* m_p;
uint m_size;
uint m_capacity;
template<typename Q> struct is_vector { enum { cFlag = false }; };
template<typename Q> struct is_vector< vector<Q> > { enum { cFlag = true }; };
static void object_mover(void* pDst_void, void* pSrc_void, uint num)
{
T* pSrc = static_cast<T*>(pSrc_void);
T* const pSrc_end = pSrc + num;
T* pDst = static_cast<T*>(pDst_void);
while (pSrc != pSrc_end)
{
new (static_cast<void*>(pDst)) T(*pSrc);
pSrc->~T();
pSrc++;
pDst++;
}
}
inline bool increase_capacity(uint min_new_capacity, bool grow_hint, bool nofail = false)
{
return reinterpret_cast<elemental_vector*>(this)->increase_capacity(
min_new_capacity, grow_hint, sizeof(T),
(LZHAM_IS_BITWISE_MOVABLE(T) || (is_vector<T>::cFlag)) ? NULL : object_mover, nofail);
}
};
template<typename T> struct bitwise_movable< vector<T> > { enum { cFlag = true }; };
extern void vector_test();
template<typename T>
inline void swap(vector<T>& a, vector<T>& b)
{
a.swap(b);
}
} // namespace lzham

View File

@ -0,0 +1,368 @@
// File: lzham_task_pool_win32.h
// See Copyright Notice and license at the end of include/lzham.h
#pragma once
#if LZHAM_USE_WIN32_API
#if LZHAM_NO_ATOMICS
#error No atomic operations defined in lzham_platform.h!
#endif
namespace lzham
{
class semaphore
{
LZHAM_NO_COPY_OR_ASSIGNMENT_OP(semaphore);
public:
semaphore(long initialCount = 0, long maximumCount = 1, const char* pName = NULL)
{
m_handle = CreateSemaphoreA(NULL, initialCount, maximumCount, pName);
if (NULL == m_handle)
{
LZHAM_FAIL("semaphore: CreateSemaphore() failed");
}
}
~semaphore()
{
if (m_handle)
{
CloseHandle(m_handle);
m_handle = NULL;
}
}
inline HANDLE get_handle(void) const { return m_handle; }
void release(long releaseCount = 1)
{
if (0 == ReleaseSemaphore(m_handle, releaseCount, NULL))
{
LZHAM_FAIL("semaphore: ReleaseSemaphore() failed");
}
}
bool wait(uint32 milliseconds = UINT32_MAX)
{
LZHAM_ASSUME(INFINITE == UINT32_MAX);
DWORD result = WaitForSingleObject(m_handle, milliseconds);
if (WAIT_FAILED == result)
{
LZHAM_FAIL("semaphore: WaitForSingleObject() failed");
}
return WAIT_OBJECT_0 == result;
}
private:
HANDLE m_handle;
};
template<typename T>
class tsstack
{
public:
inline tsstack(bool use_freelist = true) :
m_use_freelist(use_freelist)
{
LZHAM_VERIFY(((ptr_bits_t)this & (LZHAM_GET_ALIGNMENT(tsstack) - 1)) == 0);
InitializeSListHead(&m_stack_head);
InitializeSListHead(&m_freelist_head);
}
inline ~tsstack()
{
clear();
}
inline void clear()
{
for ( ; ; )
{
node* pNode = (node*)InterlockedPopEntrySList(&m_stack_head);
if (!pNode)
break;
LZHAM_MEMORY_IMPORT_BARRIER
helpers::destruct(&pNode->m_obj);
lzham_free(pNode);
}
flush_freelist();
}
inline void flush_freelist()
{
if (!m_use_freelist)
return;
for ( ; ; )
{
node* pNode = (node*)InterlockedPopEntrySList(&m_freelist_head);
if (!pNode)
break;
LZHAM_MEMORY_IMPORT_BARRIER
lzham_free(pNode);
}
}
inline bool try_push(const T& obj)
{
node* pNode = alloc_node();
if (!pNode)
return false;
helpers::construct(&pNode->m_obj, obj);
LZHAM_MEMORY_EXPORT_BARRIER
InterlockedPushEntrySList(&m_stack_head, &pNode->m_slist_entry);
return true;
}
inline bool pop(T& obj)
{
node* pNode = (node*)InterlockedPopEntrySList(&m_stack_head);
if (!pNode)
return false;
LZHAM_MEMORY_IMPORT_BARRIER
obj = pNode->m_obj;
helpers::destruct(&pNode->m_obj);
free_node(pNode);
return true;
}
private:
SLIST_HEADER m_stack_head;
SLIST_HEADER m_freelist_head;
struct node
{
SLIST_ENTRY m_slist_entry;
T m_obj;
};
bool m_use_freelist;
inline node* alloc_node()
{
node* pNode = m_use_freelist ? (node*)InterlockedPopEntrySList(&m_freelist_head) : NULL;
if (!pNode)
pNode = (node*)lzham_malloc(sizeof(node));
return pNode;
}
inline void free_node(node* pNode)
{
if (m_use_freelist)
InterlockedPushEntrySList(&m_freelist_head, &pNode->m_slist_entry);
else
lzham_free(pNode);
}
};
class task_pool
{
public:
task_pool();
task_pool(uint num_threads);
~task_pool();
enum { cMaxThreads = LZHAM_MAX_HELPER_THREADS };
bool init(uint num_threads);
void deinit();
inline uint get_num_threads() const { return m_num_threads; }
inline uint get_num_outstanding_tasks() const { return m_num_outstanding_tasks; }
// C-style task callback
typedef void (*task_callback_func)(uint64 data, void* pData_ptr);
bool queue_task(task_callback_func pFunc, uint64 data = 0, void* pData_ptr = NULL);
class executable_task
{
public:
virtual void execute_task(uint64 data, void* pData_ptr) = 0;
};
// It's the caller's responsibility to delete pObj within the execute_task() method, if needed!
bool queue_task(executable_task* pObj, uint64 data = 0, void* pData_ptr = NULL);
template<typename S, typename T>
inline bool queue_object_task(S* pObject, T pObject_method, uint64 data = 0, void* pData_ptr = NULL);
template<typename S, typename T>
inline bool queue_multiple_object_tasks(S* pObject, T pObject_method, uint64 first_data, uint num_tasks, void* pData_ptr = NULL);
void join();
private:
struct task
{
//inline task() : m_data(0), m_pData_ptr(NULL), m_pObj(NULL), m_flags(0) { }
uint64 m_data;
void* m_pData_ptr;
union
{
task_callback_func m_callback;
executable_task* m_pObj;
};
uint m_flags;
};
tsstack<task> m_task_stack;
uint m_num_threads;
HANDLE m_threads[cMaxThreads];
semaphore m_tasks_available;
enum task_flags
{
cTaskFlagObject = 1
};
volatile atomic32_t m_num_outstanding_tasks;
volatile atomic32_t m_exit_flag;
void process_task(task& tsk);
static unsigned __stdcall thread_func(void* pContext);
};
enum object_task_flags
{
cObjectTaskFlagDefault = 0,
cObjectTaskFlagDeleteAfterExecution = 1
};
template<typename T>
class object_task : public task_pool::executable_task
{
public:
object_task(uint flags = cObjectTaskFlagDefault) :
m_pObject(NULL),
m_pMethod(NULL),
m_flags(flags)
{
}
typedef void (T::*object_method_ptr)(uint64 data, void* pData_ptr);
object_task(T* pObject, object_method_ptr pMethod, uint flags = cObjectTaskFlagDefault) :
m_pObject(pObject),
m_pMethod(pMethod),
m_flags(flags)
{
LZHAM_ASSERT(pObject && pMethod);
}
void init(T* pObject, object_method_ptr pMethod, uint flags = cObjectTaskFlagDefault)
{
LZHAM_ASSERT(pObject && pMethod);
m_pObject = pObject;
m_pMethod = pMethod;
m_flags = flags;
}
T* get_object() const { return m_pObject; }
object_method_ptr get_method() const { return m_pMethod; }
virtual void execute_task(uint64 data, void* pData_ptr)
{
(m_pObject->*m_pMethod)(data, pData_ptr);
if (m_flags & cObjectTaskFlagDeleteAfterExecution)
lzham_delete(this);
}
protected:
T* m_pObject;
object_method_ptr m_pMethod;
uint m_flags;
};
template<typename S, typename T>
inline bool task_pool::queue_object_task(S* pObject, T pObject_method, uint64 data, void* pData_ptr)
{
object_task<S> *pTask = lzham_new< object_task<S> >(pObject, pObject_method, cObjectTaskFlagDeleteAfterExecution);
if (!pTask)
return false;
return queue_task(pTask, data, pData_ptr);
}
template<typename S, typename T>
inline bool task_pool::queue_multiple_object_tasks(S* pObject, T pObject_method, uint64 first_data, uint num_tasks, void* pData_ptr)
{
LZHAM_ASSERT(m_num_threads);
LZHAM_ASSERT(pObject);
LZHAM_ASSERT(num_tasks);
if (!num_tasks)
return true;
bool status = true;
uint i;
for (i = 0; i < num_tasks; i++)
{
task tsk;
tsk.m_pObj = lzham_new< object_task<S> >(pObject, pObject_method, cObjectTaskFlagDeleteAfterExecution);
if (!tsk.m_pObj)
{
status = false;
break;
}
tsk.m_data = first_data + i;
tsk.m_pData_ptr = pData_ptr;
tsk.m_flags = cTaskFlagObject;
if (!m_task_stack.try_push(tsk))
{
status = false;
break;
}
}
if (i)
{
atomic_add32(&m_num_outstanding_tasks, i);
m_tasks_available.release(i);
}
return status;
}
inline void lzham_sleep(unsigned int milliseconds)
{
Sleep(milliseconds);
}
uint lzham_get_max_helper_threads();
} // namespace lzham
#endif // LZHAM_USE_WIN32_API

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

179
r5dev/thirdparty/lzham/lzham_api.cpp vendored Normal file
View File

@ -0,0 +1,179 @@
// File: lzham_api.cpp - Dynamic DLL entrypoints.
// See Copyright Notice and license at the end of include/lzham.h
#include "include/lzham_core.h"
#include "lzhamdecomp/lzham_decomp.h"
#include "lzhamcomp/lzham_comp.h"
extern "C" LZHAM_DLL_EXPORT lzham_uint32 lzham_get_version(void)
{
return LZHAM_DLL_VERSION;
}
extern "C" LZHAM_DLL_EXPORT void lzham_set_memory_callbacks(lzham_realloc_func pRealloc, lzham_msize_func pMSize, void* pUser_data)
{
lzham::lzham_lib_set_memory_callbacks(pRealloc, pMSize, pUser_data);
}
extern "C" LZHAM_DLL_EXPORT lzham_decompress_state_ptr lzham_decompress_init(const lzham_decompress_params *pParams)
{
return lzham::lzham_lib_decompress_init(pParams);
}
extern "C" LZHAM_DLL_EXPORT lzham_decompress_state_ptr lzham_decompress_reinit(lzham_decompress_state_ptr p, const lzham_decompress_params *pParams)
{
return lzham::lzham_lib_decompress_reinit(p, pParams);
}
extern "C" LZHAM_DLL_EXPORT lzham_decompress_checksums* lzham_decompress_deinit(lzham_decompress_state_ptr p)
{
return lzham::lzham_lib_decompress_deinit(p);
}
extern "C" LZHAM_DLL_EXPORT lzham_decompress_status_t lzham_decompress(
lzham_decompress_state_ptr p,
const lzham_uint8 *pIn_buf, size_t *pIn_buf_size,
lzham_uint8 *pOut_buf, size_t *pOut_buf_size,
lzham_bool no_more_input_bytes_flag)
{
return lzham::lzham_lib_decompress(p, pIn_buf, pIn_buf_size, pOut_buf, pOut_buf_size, no_more_input_bytes_flag);
}
extern "C" LZHAM_DLL_EXPORT lzham_decompress_status_t lzham_decompress_memory(const lzham_decompress_params *pParams, lzham_uint8* pDst_buf, size_t *pDst_len, const lzham_uint8* pSrc_buf, size_t src_len, lzham_uint32 *pAdler32, lzham_uint32 *pCrc32)
{
return lzham::lzham_lib_decompress_memory(pParams, pDst_buf, pDst_len, pSrc_buf, src_len, pAdler32, pCrc32);
}
extern "C" LZHAM_DLL_EXPORT lzham_compress_state_ptr lzham_compress_init(const lzham_compress_params *pParams)
{
return lzham::lzham_lib_compress_init(pParams);
}
extern "C" LZHAM_DLL_EXPORT lzham_compress_state_ptr lzham_compress_reinit(lzham_compress_state_ptr p)
{
return lzham::lzham_lib_compress_reinit(p);
}
extern "C" LZHAM_DLL_EXPORT lzham_compress_checksums* lzham_compress_deinit(lzham_compress_state_ptr p)
{
return lzham::lzham_lib_compress_deinit(p);
}
extern "C" LZHAM_DLL_EXPORT lzham_compress_status_t lzham_compress(
lzham_compress_state_ptr p,
const lzham_uint8 *pIn_buf, size_t *pIn_buf_size,
lzham_uint8 *pOut_buf, size_t *pOut_buf_size,
lzham_bool no_more_input_bytes_flag)
{
return lzham::lzham_lib_compress(p, pIn_buf, pIn_buf_size, pOut_buf, pOut_buf_size, no_more_input_bytes_flag);
}
extern "C" LZHAM_DLL_EXPORT lzham_compress_status_t lzham_compress2(
lzham_compress_state_ptr p,
const lzham_uint8 *pIn_buf, size_t *pIn_buf_size,
lzham_uint8 *pOut_buf, size_t *pOut_buf_size,
lzham_flush_t flush_type)
{
return lzham::lzham_lib_compress2(p, pIn_buf, pIn_buf_size, pOut_buf, pOut_buf_size, flush_type);
}
extern "C" LZHAM_DLL_EXPORT lzham_compress_status_t lzham_compress_memory(const lzham_compress_params *pParams, lzham_uint8* pDst_buf, size_t *pDst_len, const lzham_uint8* pSrc_buf, size_t src_len, lzham_uint32 *pAdler32, lzham_uint32 * pCrc32)
{
return lzham::lzham_lib_compress_memory(pParams, pDst_buf, pDst_len, pSrc_buf, src_len, pAdler32, pCrc32);
}
// ----------------- zlib-style API's
extern "C" LZHAM_DLL_EXPORT const char *lzham_z_version(void)
{
return LZHAM_Z_VERSION;
}
extern "C" lzham_z_ulong LZHAM_DLL_EXPORT lzham_z_adler32(lzham_z_ulong adler, const unsigned char *ptr, size_t buf_len)
{
return lzham::lzham_lib_z_adler32(adler, ptr, buf_len);
}
extern "C" lzham_z_ulong LZHAM_DLL_EXPORT lzham_z_crc32(lzham_z_ulong crc, const lzham_uint8 *ptr, size_t buf_len)
{
return lzham::lzham_lib_z_crc32(crc, ptr, buf_len);
}
extern "C" LZHAM_DLL_EXPORT int lzham_z_deflateInit(lzham_z_streamp pStream, int level)
{
return lzham::lzham_lib_z_deflateInit(pStream, level);
}
extern "C" LZHAM_DLL_EXPORT int lzham_z_deflateInit2(lzham_z_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
{
return lzham::lzham_lib_z_deflateInit2(pStream, level, method, window_bits, mem_level, strategy);
}
extern "C" LZHAM_DLL_EXPORT int lzham_z_deflateReset(lzham_z_streamp pStream)
{
return lzham::lzham_lib_z_deflateReset(pStream);
}
extern "C" LZHAM_DLL_EXPORT int lzham_z_deflate(lzham_z_streamp pStream, int flush)
{
return lzham::lzham_lib_z_deflate(pStream, flush);
}
extern "C" LZHAM_DLL_EXPORT int lzham_z_deflateEnd(lzham_z_streamp pStream)
{
return lzham::lzham_lib_z_deflateEnd(pStream);
}
extern "C" LZHAM_DLL_EXPORT lzham_z_ulong lzham_z_deflateBound(lzham_z_streamp pStream, lzham_z_ulong source_len)
{
return lzham::lzham_lib_z_deflateBound(pStream, source_len);
}
extern "C" LZHAM_DLL_EXPORT int lzham_z_compress(unsigned char *pDest, lzham_z_ulong *pDest_len, const unsigned char *pSource, lzham_z_ulong source_len)
{
return lzham::lzham_lib_z_compress(pDest, pDest_len, pSource, source_len);
}
extern "C" LZHAM_DLL_EXPORT int lzham_z_compress2(unsigned char *pDest, lzham_z_ulong *pDest_len, const unsigned char *pSource, lzham_z_ulong source_len, int level)
{
return lzham::lzham_lib_z_compress2(pDest, pDest_len, pSource, source_len, level);
}
extern "C" LZHAM_DLL_EXPORT lzham_z_ulong lzham_z_compressBound(lzham_z_ulong source_len)
{
return lzham::lzham_lib_z_compressBound(source_len);
}
extern "C" LZHAM_DLL_EXPORT int lzham_z_inflateInit(lzham_z_streamp pStream)
{
return lzham::lzham_lib_z_inflateInit(pStream);
}
extern "C" LZHAM_DLL_EXPORT int lzham_z_inflateInit2(lzham_z_streamp pStream, int window_bits)
{
return lzham::lzham_lib_z_inflateInit2(pStream, window_bits);
}
extern "C" LZHAM_DLL_EXPORT int lzham_z_inflateReset(lzham_z_streamp pStream)
{
return lzham::lzham_lib_z_inflateReset(pStream);
}
extern "C" LZHAM_DLL_EXPORT int lzham_z_inflate(lzham_z_streamp pStream, int flush)
{
return lzham::lzham_lib_z_inflate(pStream, flush);
}
extern "C" LZHAM_DLL_EXPORT int lzham_z_inflateEnd(lzham_z_streamp pStream)
{
return lzham::lzham_lib_z_inflateEnd(pStream);
}
extern "C" LZHAM_DLL_EXPORT int lzham_z_uncompress(unsigned char *pDest, lzham_z_ulong *pDest_len, const unsigned char *pSource, lzham_z_ulong source_len)
{
return lzham::lzham_lib_z_uncompress(pDest, pDest_len, pSource, source_len);
}
extern "C" LZHAM_DLL_EXPORT const char *lzham_z_error(int err)
{
return lzham::lzham_lib_z_error(err);
}

66
r5dev/thirdparty/lzham/lzham_assert.cpp vendored Normal file
View File

@ -0,0 +1,66 @@
// File: lzham_assert.cpp
// See Copyright Notice and license at the end of include/lzham.h
#include "include/lzham_core.h"
static bool g_fail_exceptions;
static bool g_exit_on_failure = true;
void lzham_enable_fail_exceptions(bool enabled)
{
g_fail_exceptions = enabled;
}
void lzham_assert(const char* pExp, const char* pFile, unsigned line)
{
char buf[512];
sprintf_s(buf, sizeof(buf), "%s(%u): Assertion failed: \"%s\"\n", pFile, line, pExp);
lzham_output_debug_string(buf);
printf("%s", buf);
if (lzham_is_debugger_present())
lzham_debug_break();
}
void lzham_fail(const char* pExp, const char* pFile, unsigned line)
{
char buf[512];
sprintf_s(buf, sizeof(buf), "%s(%u): Failure: \"%s\"\n", pFile, line, pExp);
lzham_output_debug_string(buf);
printf("%s", buf);
if (lzham_is_debugger_present())
lzham_debug_break();
#if LZHAM_USE_WIN32_API
if (g_fail_exceptions)
RaiseException(LZHAM_FAIL_EXCEPTION_CODE, 0, 0, NULL);
else
#endif
if (g_exit_on_failure)
exit(EXIT_FAILURE);
}
void lzham_trace(const char* pFmt, va_list args)
{
if (lzham_is_debugger_present())
{
char buf[512];
vsprintf_s(buf, sizeof(buf), pFmt, args);
lzham_output_debug_string(buf);
}
};
void lzham_trace(const char* pFmt, ...)
{
va_list args;
va_start(args, pFmt);
lzham_trace(pFmt, args);
va_end(args);
};

View File

@ -0,0 +1,73 @@
// File: lzham_checksum.cpp
#include "include/lzham_core.h"
#include "include/lzham_checksum.h"
namespace lzham
{
// Originally from the public domain stb.h header.
uint adler32(const void* pBuf, size_t buflen, uint adler32)
{
if (!pBuf)
return cInitAdler32;
const uint8* buffer = static_cast<const uint8*>(pBuf);
const unsigned long ADLER_MOD = 65521;
unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
size_t blocklen;
unsigned long i;
blocklen = buflen % 5552;
while (buflen)
{
for (i=0; i + 7 < blocklen; i += 8)
{
s1 += buffer[0], s2 += s1;
s1 += buffer[1], s2 += s1;
s1 += buffer[2], s2 += s1;
s1 += buffer[3], s2 += s1;
s1 += buffer[4], s2 += s1;
s1 += buffer[5], s2 += s1;
s1 += buffer[6], s2 += s1;
s1 += buffer[7], s2 += s1;
buffer += 8;
}
for (; i < blocklen; ++i)
s1 += *buffer++, s2 += s1;
s1 %= ADLER_MOD, s2 %= ADLER_MOD;
buflen -= blocklen;
blocklen = 5552;
}
return (s2 << 16) + s1;
}
// Karl Malbrain's compact CRC-32, with pre and post conditioning.
// See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed":
// http://www.geocities.com/malbrain/
static const lzham_uint32 s_crc32[16] =
{
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
uint crc32(uint crc, const lzham_uint8 *ptr, size_t buf_len)
{
if (!ptr)
return cInitCRC32;
crc = ~crc;
while (buf_len--)
{
lzham_uint8 b = *ptr++;
crc = (crc >> 4) ^ s_crc32[(crc & 0xF) ^ (b & 0xF)];
crc = (crc >> 4) ^ s_crc32[(crc & 0xF) ^ (b >> 4)];
}
return ~crc;
}
} // namespace lzham

View File

@ -0,0 +1,390 @@
// File: huffman_codes.cpp
// See Copyright Notice and license at the end of include/lzham.h
#include "include/lzham_core.h"
#include "include/lzham_huffman_codes.h"
namespace lzham
{
struct sym_freq
{
uint m_freq;
uint16 m_left;
uint16 m_right;
inline bool operator< (const sym_freq& other) const
{
return m_freq > other.m_freq;
}
};
static inline sym_freq* radix_sort_syms(uint num_syms, sym_freq* syms0, sym_freq* syms1)
{
const uint cMaxPasses = 2;
uint hist[256 * cMaxPasses];
memset(hist, 0, sizeof(hist[0]) * 256 * cMaxPasses);
{
sym_freq* p = syms0;
sym_freq* q = syms0 + (num_syms >> 1) * 2;
for ( ; p != q; p += 2)
{
const uint freq0 = p[0].m_freq;
const uint freq1 = p[1].m_freq;
hist[ freq0 & 0xFF]++;
hist[256 + ((freq0 >> 8) & 0xFF)]++;
hist[ freq1 & 0xFF]++;
hist[256 + ((freq1 >> 8) & 0xFF)]++;
}
if (num_syms & 1)
{
const uint freq = p->m_freq;
hist[ freq & 0xFF]++;
hist[256 + ((freq >> 8) & 0xFF)]++;
}
}
sym_freq* pCur_syms = syms0;
sym_freq* pNew_syms = syms1;
const uint total_passes = (hist[256] == num_syms) ? 1 : cMaxPasses;
for (uint pass = 0; pass < total_passes; pass++)
{
const uint* pHist = &hist[pass << 8];
uint offsets[256];
uint cur_ofs = 0;
for (uint i = 0; i < 256; i += 2)
{
offsets[i] = cur_ofs;
cur_ofs += pHist[i];
offsets[i+1] = cur_ofs;
cur_ofs += pHist[i+1];
}
const uint pass_shift = pass << 3;
sym_freq* p = pCur_syms;
sym_freq* q = pCur_syms + (num_syms >> 1) * 2;
for ( ; p != q; p += 2)
{
uint c0 = p[0].m_freq;
uint c1 = p[1].m_freq;
if (pass)
{
c0 >>= 8;
c1 >>= 8;
}
c0 &= 0xFF;
c1 &= 0xFF;
if (c0 == c1)
{
uint dst_offset0 = offsets[c0];
offsets[c0] = dst_offset0 + 2;
pNew_syms[dst_offset0] = p[0];
pNew_syms[dst_offset0 + 1] = p[1];
}
else
{
uint dst_offset0 = offsets[c0]++;
uint dst_offset1 = offsets[c1]++;
pNew_syms[dst_offset0] = p[0];
pNew_syms[dst_offset1] = p[1];
}
}
if (num_syms & 1)
{
uint c = ((p->m_freq) >> pass_shift) & 0xFF;
uint dst_offset = offsets[c];
offsets[c] = dst_offset + 1;
pNew_syms[dst_offset] = *p;
}
sym_freq* t = pCur_syms;
pCur_syms = pNew_syms;
pNew_syms = t;
}
#if LZHAM_ASSERTS_ENABLED
uint prev_freq = 0;
for (uint i = 0; i < num_syms; i++)
{
LZHAM_ASSERT(!(pCur_syms[i].m_freq < prev_freq));
prev_freq = pCur_syms[i].m_freq;
}
#endif
return pCur_syms;
}
struct huffman_work_tables
{
enum { cMaxInternalNodes = cHuffmanMaxSupportedSyms };
sym_freq syms0[cHuffmanMaxSupportedSyms + 1 + cMaxInternalNodes];
sym_freq syms1[cHuffmanMaxSupportedSyms + 1 + cMaxInternalNodes];
#if !USE_CALCULATE_MINIMUM_REDUNDANCY
uint16 queue[cMaxInternalNodes];
#endif
};
uint get_generate_huffman_codes_table_size()
{
return sizeof(huffman_work_tables);
}
#define USE_CALCULATE_MINIMUM_REDUNDANCY 1
#if USE_CALCULATE_MINIMUM_REDUNDANCY
/* calculate_minimum_redundancy() written by
Alistair Moffat, alistair@cs.mu.oz.au,
Jyrki Katajainen, jyrki@diku.dk
November 1996.
*/
static void calculate_minimum_redundancy(int A[], int n) {
int root; /* next root node to be used */
int leaf; /* next leaf to be used */
int next; /* next value to be assigned */
int avbl; /* number of available nodes */
int used; /* number of internal nodes */
int dpth; /* current depth of leaves */
/* check for pathological cases */
if (n==0) { return; }
if (n==1) { A[0] = 0; return; }
/* first pass, left to right, setting parent pointers */
A[0] += A[1]; root = 0; leaf = 2;
for (next=1; next < n-1; next++) {
/* select first item for a pairing */
if (leaf>=n || A[root]<A[leaf]) {
A[next] = A[root]; A[root++] = next;
} else
A[next] = A[leaf++];
/* add on the second item */
if (leaf>=n || (root<next && A[root]<A[leaf])) {
A[next] += A[root]; A[root++] = next;
} else
A[next] += A[leaf++];
}
/* second pass, right to left, setting internal depths */
A[n-2] = 0;
for (next=n-3; next>=0; next--)
A[next] = A[A[next]]+1;
/* third pass, right to left, setting leaf depths */
avbl = 1; used = dpth = 0; root = n-2; next = n-1;
while (avbl>0) {
while (root>=0 && A[root]==dpth) {
used++; root--;
}
while (avbl>used) {
A[next--] = dpth; avbl--;
}
avbl = 2*used; dpth++; used = 0;
}
}
#endif
bool generate_huffman_codes(void* pContext, uint num_syms, const uint16* pFreq, uint8* pCodesizes, uint& max_code_size, uint& total_freq_ret)
{
if ((!num_syms) || (num_syms > cHuffmanMaxSupportedSyms))
return false;
huffman_work_tables& state = *static_cast<huffman_work_tables*>(pContext);;
uint max_freq = 0;
uint total_freq = 0;
uint num_used_syms = 0;
for (uint i = 0; i < num_syms; i++)
{
uint freq = pFreq[i];
if (!freq)
pCodesizes[i] = 0;
else
{
total_freq += freq;
max_freq = math::maximum(max_freq, freq);
sym_freq& sf = state.syms0[num_used_syms];
sf.m_left = (uint16)i;
sf.m_right = UINT16_MAX;
sf.m_freq = freq;
num_used_syms++;
}
}
total_freq_ret = total_freq;
if (num_used_syms == 1)
{
pCodesizes[state.syms0[0].m_left] = 1;
return true;
}
sym_freq* syms = radix_sort_syms(num_used_syms, state.syms0, state.syms1);
#if USE_CALCULATE_MINIMUM_REDUNDANCY
int x[cHuffmanMaxSupportedSyms];
for (uint i = 0; i < num_used_syms; i++)
x[i] = syms[i].m_freq;
calculate_minimum_redundancy(x, num_used_syms);
uint max_len = 0;
for (uint i = 0; i < num_used_syms; i++)
{
uint len = x[i];
max_len = math::maximum(len, max_len);
pCodesizes[syms[i].m_left] = static_cast<uint8>(len);
}
max_code_size = max_len;
#else
// Computes Huffman codelengths in linear time. More readable than calculate_minimum_redundancy(), and approximately the same speed, but not in-place.
// Dummy node
sym_freq& sf = state.syms0[num_used_syms];
sf.m_left = UINT16_MAX;
sf.m_right = UINT16_MAX;
sf.m_freq = UINT_MAX;
uint next_internal_node = num_used_syms + 1;
uint queue_front = 0;
uint queue_end = 0;
uint next_lowest_sym = 0;
uint num_nodes_remaining = num_used_syms;
do
{
uint left_freq = syms[next_lowest_sym].m_freq;
uint left_child = next_lowest_sym;
if ((queue_end > queue_front) && (syms[state.queue[queue_front]].m_freq < left_freq))
{
left_child = state.queue[queue_front];
left_freq = syms[left_child].m_freq;
queue_front++;
}
else
next_lowest_sym++;
uint right_freq = syms[next_lowest_sym].m_freq;
uint right_child = next_lowest_sym;
if ((queue_end > queue_front) && (syms[state.queue[queue_front]].m_freq < right_freq))
{
right_child = state.queue[queue_front];
right_freq = syms[right_child].m_freq;
queue_front++;
}
else
next_lowest_sym++;
LZHAM_ASSERT(next_internal_node < huffman_work_tables::cMaxInternalNodes);
const uint internal_node_index = next_internal_node;
next_internal_node++;
syms[internal_node_index].m_freq = left_freq + right_freq;
syms[internal_node_index].m_left = static_cast<uint16>(left_child);
syms[internal_node_index].m_right = static_cast<uint16>(right_child);
LZHAM_ASSERT(queue_end < huffman_work_tables::cMaxInternalNodes);
state.queue[queue_end] = static_cast<uint16>(internal_node_index);
queue_end++;
num_nodes_remaining--;
} while (num_nodes_remaining > 1);
LZHAM_ASSERT(next_lowest_sym == num_used_syms);
LZHAM_ASSERT((queue_end - queue_front) == 1);
uint cur_node_index = state.queue[queue_front];
uint32* pStack = (syms == state.syms0) ? (uint32*)state.syms1 : (uint32*)state.syms0;
uint32* pStack_top = pStack;
uint max_level = 0;
for ( ; ; )
{
uint level = cur_node_index >> 16;
uint node_index = cur_node_index & 0xFFFF;
uint left_child = syms[node_index].m_left;
uint right_child = syms[node_index].m_right;
uint next_level = (cur_node_index + 0x10000) & 0xFFFF0000;
if (left_child < num_used_syms)
{
max_level = math::maximum(max_level, level);
pCodesizes[syms[left_child].m_left] = static_cast<uint8>(level + 1);
if (right_child < num_used_syms)
{
pCodesizes[syms[right_child].m_left] = static_cast<uint8>(level + 1);
if (pStack == pStack_top) break;
cur_node_index = *--pStack;
}
else
{
cur_node_index = next_level | right_child;
}
}
else
{
if (right_child < num_used_syms)
{
max_level = math::maximum(max_level, level);
pCodesizes[syms[right_child].m_left] = static_cast<uint8>(level + 1);
cur_node_index = next_level | left_child;
}
else
{
*pStack++ = next_level | left_child;
cur_node_index = next_level | right_child;
}
}
}
max_code_size = max_level + 1;
#endif
return true;
}
} // namespace lzham

71
r5dev/thirdparty/lzham/lzham_lzbase.cpp vendored Normal file
View File

@ -0,0 +1,71 @@
// File: lzham_lzbase.cpp
// See Copyright Notice and license at the end of include/lzham.h
#include "include/lzham_core.h"
#include "include/lzham_lzbase.h"
namespace lzham
{
void CLZBase::init_slot_tabs()
{
for (uint i = 0; i < m_num_lzx_slots; i++)
{
//printf("%u: 0x%08X - 0x%08X, %u\n", i, m_lzx_position_base[i], m_lzx_position_base[i] + (1 << m_lzx_position_extra_bits[i]) - 1, m_lzx_position_extra_bits[i]);
uint lo = m_lzx_position_base[i];
uint hi = lo + m_lzx_position_extra_mask[i];
uint8* pTab;
uint shift;
uint n; LZHAM_NOTE_UNUSED(n);
if (hi < 0x1000)
{
pTab = m_slot_tab0;
shift = 0;
n = sizeof(m_slot_tab0);
}
else if (hi < 0x100000)
{
pTab = m_slot_tab1;
shift = 11;
n = sizeof(m_slot_tab1);
}
else if (hi < 0x1000000)
{
pTab = m_slot_tab2;
shift = 16;
n = sizeof(m_slot_tab2);
}
else
break;
lo >>= shift;
hi >>= shift;
LZHAM_ASSERT(hi < n);
memset(pTab + lo, (uint8)i, hi - lo + 1);
}
#ifdef LZHAM_BUILD_DEBUG
uint slot, ofs;
for (uint i = 1; i < m_num_lzx_slots; i++)
{
compute_lzx_position_slot(m_lzx_position_base[i], slot, ofs);
LZHAM_ASSERT(slot == i);
compute_lzx_position_slot(m_lzx_position_base[i] + m_lzx_position_extra_mask[i], slot, ofs);
LZHAM_ASSERT(slot == i);
}
for (uint i = 1; i <= (m_dict_size-1); i += 512U*1024U)
{
compute_lzx_position_slot(i, slot, ofs);
LZHAM_ASSERT(i == m_lzx_position_base[slot] + ofs);
}
compute_lzx_position_slot(m_dict_size - 1, slot, ofs);
LZHAM_ASSERT((m_dict_size - 1) == m_lzx_position_base[slot] + ofs);
#endif
}
} //namespace lzham

View File

@ -0,0 +1,562 @@
// File: lzham_match_accel.cpp
// See Copyright Notice and license at the end of include/lzham.h
#include "include/lzham_core.h"
#include "include/lzham_match_accel.h"
#include "include/lzham_timer.h"
namespace lzham
{
static inline uint32 hash2_to_12(uint c0, uint c1)
{
return c0 ^ (c1 << 4);
}
static inline uint32 hash3_to_16(uint c0, uint c1, uint c2)
{
return (c0 | (c1 << 8)) ^ (c2 << 4);
}
search_accelerator::search_accelerator() :
m_pLZBase(NULL),
m_pTask_pool(NULL),
m_max_helper_threads(0),
m_max_dict_size(0),
m_max_dict_size_mask(0),
m_lookahead_pos(0),
m_lookahead_size(0),
m_cur_dict_size(0),
m_fill_lookahead_pos(0),
m_fill_lookahead_size(0),
m_fill_dict_size(0),
m_max_probes(0),
m_max_matches(0),
m_all_matches(false),
m_next_match_ref(0),
m_num_completed_helper_threads(0)
{
}
bool search_accelerator::init(CLZBase* pLZBase, task_pool* pPool, uint max_helper_threads, uint max_dict_size, uint max_matches, bool all_matches, uint max_probes)
{
LZHAM_ASSERT(pLZBase);
LZHAM_ASSERT(max_dict_size && math::is_power_of_2(max_dict_size));
LZHAM_ASSERT(max_probes);
m_max_probes = LZHAM_MIN(cMatchAccelMaxSupportedProbes, max_probes);
m_pLZBase = pLZBase;
m_pTask_pool = max_helper_threads ? pPool : NULL;
m_max_helper_threads = m_pTask_pool ? max_helper_threads : 0;
m_max_matches = LZHAM_MIN(m_max_probes, max_matches);
m_all_matches = all_matches;
m_max_dict_size = max_dict_size;
m_max_dict_size_mask = m_max_dict_size - 1;
m_cur_dict_size = 0;
m_lookahead_size = 0;
m_lookahead_pos = 0;
m_fill_lookahead_pos = 0;
m_fill_lookahead_size = 0;
m_fill_dict_size = 0;
m_num_completed_helper_threads = 0;
if (!m_dict.try_resize_no_construct(max_dict_size + LZHAM_MIN(m_max_dict_size, static_cast<uint>(CLZBase::cMaxHugeMatchLen))))
return false;
if (!m_hash.try_resize_no_construct(cHashSize))
return false;
if (!m_nodes.try_resize_no_construct(max_dict_size))
return false;
memset(m_hash.get_ptr(), 0, m_hash.size_in_bytes());
return true;
}
void search_accelerator::reset()
{
m_cur_dict_size = 0;
m_lookahead_size = 0;
m_lookahead_pos = 0;
m_fill_lookahead_pos = 0;
m_fill_lookahead_size = 0;
m_fill_dict_size = 0;
m_num_completed_helper_threads = 0;
// Clearing the hash tables is only necessary for determinism (otherwise, it's possible the matches returned after a reset will depend on the data processes before the reset).
if (m_hash.size())
memset(m_hash.get_ptr(), 0, m_hash.size_in_bytes());
if (m_digram_hash.size())
memset(m_digram_hash.get_ptr(), 0, m_digram_hash.size_in_bytes());
}
void search_accelerator::flush()
{
m_cur_dict_size = 0;
}
uint search_accelerator::get_max_add_bytes() const
{
uint add_pos = static_cast<uint>(m_lookahead_pos & (m_max_dict_size - 1));
return m_max_dict_size - add_pos;
}
static uint8 g_hamming_dist[256] =
{
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};
void search_accelerator::find_all_matches_callback(uint64 data, void* pData_ptr)
{
scoped_perf_section find_all_matches_timer("find_all_matches_callback");
LZHAM_NOTE_UNUSED(pData_ptr);
const uint thread_index = (uint)data;
dict_match temp_matches[cMatchAccelMaxSupportedProbes * 2];
uint fill_lookahead_pos = m_fill_lookahead_pos;
uint fill_dict_size = m_fill_dict_size;
uint fill_lookahead_size = m_fill_lookahead_size;
uint c0 = 0, c1 = 0;
if (fill_lookahead_size >= 2)
{
c0 = m_dict[fill_lookahead_pos & m_max_dict_size_mask];
c1 = m_dict[(fill_lookahead_pos & m_max_dict_size_mask) + 1];
}
const uint8* pDict = m_dict.get_ptr();
while (fill_lookahead_size >= 3)
{
uint insert_pos = fill_lookahead_pos & m_max_dict_size_mask;
uint c2 = pDict[insert_pos + 2];
uint h = hash3_to_16(c0, c1, c2);
c0 = c1;
c1 = c2;
LZHAM_ASSERT(!m_hash_thread_index.size() || (m_hash_thread_index[h] != UINT8_MAX));
// Only process those strings that this worker thread was assigned to - this allows us to manipulate multiple trees in parallel with no worries about synchronization.
if (m_hash_thread_index.size() && (m_hash_thread_index[h] != thread_index))
{
fill_lookahead_pos++;
fill_lookahead_size--;
fill_dict_size++;
continue;
}
dict_match* pDstMatch = temp_matches;
uint cur_pos = m_hash[h];
m_hash[h] = static_cast<uint>(fill_lookahead_pos);
uint *pLeft = &m_nodes[insert_pos].m_left;
uint *pRight = &m_nodes[insert_pos].m_right;
const uint max_match_len = LZHAM_MIN(static_cast<uint>(CLZBase::cMaxMatchLen), fill_lookahead_size);
uint best_match_len = 2;
const uint8* pIns = &pDict[insert_pos];
uint n = m_max_probes;
for ( ; ; )
{
uint delta_pos = fill_lookahead_pos - cur_pos;
if ((n-- == 0) || (!delta_pos) || (delta_pos >= fill_dict_size))
{
*pLeft = 0;
*pRight = 0;
break;
}
uint pos = cur_pos & m_max_dict_size_mask;
node *pNode = &m_nodes[pos];
// Unfortunately, the initial compare match_len must be 0 because of the way we hash and truncate matches at the end of each block.
uint match_len = 0;
const uint8* pComp = &pDict[pos];
#if LZHAM_PLATFORM_X360
for ( ; match_len < max_match_len; match_len++)
if (pComp[match_len] != pIns[match_len])
break;
#else
// Compare a qword at a time for a bit more efficiency.
const uint64* pComp_end = reinterpret_cast<const uint64*>(pComp + max_match_len - 7);
const uint64* pComp_cur = reinterpret_cast<const uint64*>(pComp);
const uint64* pIns_cur = reinterpret_cast<const uint64*>(pIns);
while (pComp_cur < pComp_end)
{
if (*pComp_cur != *pIns_cur)
break;
pComp_cur++;
pIns_cur++;
}
uint alt_match_len = static_cast<uint>(reinterpret_cast<const uint8*>(pComp_cur) - reinterpret_cast<const uint8*>(pComp));
for ( ; alt_match_len < max_match_len; alt_match_len++)
if (pComp[alt_match_len] != pIns[alt_match_len])
break;
#ifdef LZVERIFY
for ( ; match_len < max_match_len; match_len++)
if (pComp[match_len] != pIns[match_len])
break;
LZHAM_VERIFY(alt_match_len == match_len);
#endif
match_len = alt_match_len;
#endif
if (match_len > best_match_len)
{
pDstMatch->m_len = static_cast<uint16>(match_len - CLZBase::cMinMatchLen);
pDstMatch->m_dist = delta_pos;
pDstMatch++;
best_match_len = match_len;
if (match_len == max_match_len)
{
*pLeft = pNode->m_left;
*pRight = pNode->m_right;
break;
}
}
else if (m_all_matches)
{
pDstMatch->m_len = static_cast<uint16>(match_len - CLZBase::cMinMatchLen);
pDstMatch->m_dist = delta_pos;
pDstMatch++;
}
else if ((best_match_len > 2) && (best_match_len == match_len))
{
uint bestMatchDist = pDstMatch[-1].m_dist;
uint compMatchDist = delta_pos;
uint bestMatchSlot, bestMatchSlotOfs;
m_pLZBase->compute_lzx_position_slot(bestMatchDist, bestMatchSlot, bestMatchSlotOfs);
uint compMatchSlot, compMatchOfs;
m_pLZBase->compute_lzx_position_slot(compMatchDist, compMatchSlot, compMatchOfs);
// If both matches uses the same match slot, choose the one with the offset containing the lowest nibble as these bits separately entropy coded.
// This could choose a match which is further away in the absolute sense, but closer in a coding sense.
if ( (compMatchSlot < bestMatchSlot) ||
((compMatchSlot >= 8) && (compMatchSlot == bestMatchSlot) && ((compMatchOfs & 15) < (bestMatchSlotOfs & 15))) )
{
LZHAM_ASSERT((pDstMatch[-1].m_len + (uint)CLZBase::cMinMatchLen) == best_match_len);
pDstMatch[-1].m_dist = delta_pos;
}
else if ((match_len < max_match_len) && (compMatchSlot <= bestMatchSlot))
{
// Choose the match which has lowest hamming distance in the mismatch byte for a tiny win on binary files.
// TODO: This competes against the prev. optimization.
uint desired_mismatch_byte = pIns[match_len];
uint cur_mismatch_byte = pDict[(insert_pos - bestMatchDist + match_len) & m_max_dict_size_mask];
uint cur_mismatch_dist = g_hamming_dist[cur_mismatch_byte ^ desired_mismatch_byte];
uint new_mismatch_byte = pComp[match_len];
uint new_mismatch_dist = g_hamming_dist[new_mismatch_byte ^ desired_mismatch_byte];
if (new_mismatch_dist < cur_mismatch_dist)
{
LZHAM_ASSERT((pDstMatch[-1].m_len + (uint)CLZBase::cMinMatchLen) == best_match_len);
pDstMatch[-1].m_dist = delta_pos;
}
}
}
uint new_pos;
if (pComp[match_len] < pIns[match_len])
{
*pLeft = cur_pos;
pLeft = &pNode->m_right;
new_pos = pNode->m_right;
}
else
{
*pRight = cur_pos;
pRight = &pNode->m_left;
new_pos = pNode->m_left;
}
if (new_pos == cur_pos)
break;
cur_pos = new_pos;
}
const uint num_matches = (uint)(pDstMatch - temp_matches);
if (num_matches)
{
pDstMatch[-1].m_dist |= 0x80000000;
const uint num_matches_to_write = LZHAM_MIN(num_matches, m_max_matches);
const uint match_ref_ofs = atomic_exchange_add(&m_next_match_ref, num_matches_to_write);
memcpy(&m_matches[match_ref_ofs],
temp_matches + (num_matches - num_matches_to_write),
sizeof(temp_matches[0]) * num_matches_to_write);
// FIXME: This is going to really hurt on platforms requiring export barriers.
LZHAM_MEMORY_EXPORT_BARRIER
atomic_exchange32((atomic32_t*)&m_match_refs[static_cast<uint>(fill_lookahead_pos - m_fill_lookahead_pos)], match_ref_ofs);
}
else
{
atomic_exchange32((atomic32_t*)&m_match_refs[static_cast<uint>(fill_lookahead_pos - m_fill_lookahead_pos)], -2);
}
fill_lookahead_pos++;
fill_lookahead_size--;
fill_dict_size++;
}
while (fill_lookahead_size)
{
uint insert_pos = fill_lookahead_pos & m_max_dict_size_mask;
m_nodes[insert_pos].m_left = 0;
m_nodes[insert_pos].m_right = 0;
atomic_exchange32((atomic32_t*)&m_match_refs[static_cast<uint>(fill_lookahead_pos - m_fill_lookahead_pos)], -2);
fill_lookahead_pos++;
fill_lookahead_size--;
fill_dict_size++;
}
atomic_increment32(&m_num_completed_helper_threads);
}
bool search_accelerator::find_len2_matches()
{
if (!m_digram_hash.size())
{
if (!m_digram_hash.try_resize(cDigramHashSize))
return false;
}
if (m_digram_next.size() < m_lookahead_size)
{
if (!m_digram_next.try_resize(m_lookahead_size))
return false;
}
uint lookahead_dict_pos = m_lookahead_pos & m_max_dict_size_mask;
for (int lookahead_ofs = 0; lookahead_ofs < ((int)m_lookahead_size - 1); ++lookahead_ofs, ++lookahead_dict_pos)
{
uint c0 = m_dict[lookahead_dict_pos];
uint c1 = m_dict[lookahead_dict_pos + 1];
uint h = hash2_to_12(c0, c1) & (cDigramHashSize - 1);
m_digram_next[lookahead_ofs] = m_digram_hash[h];
m_digram_hash[h] = m_lookahead_pos + lookahead_ofs;
}
m_digram_next[m_lookahead_size - 1] = 0;
return true;
}
uint search_accelerator::get_len2_match(uint lookahead_ofs)
{
if ((m_fill_lookahead_size - lookahead_ofs) < 2)
return 0;
uint cur_pos = m_lookahead_pos + lookahead_ofs;
uint next_match_pos = m_digram_next[cur_pos - m_fill_lookahead_pos];
uint match_dist = cur_pos - next_match_pos;
if ((!match_dist) || (match_dist > CLZBase::cMaxLen2MatchDist) || (match_dist > (m_cur_dict_size + lookahead_ofs)))
return 0;
const uint8* pCur = &m_dict[cur_pos & m_max_dict_size_mask];
const uint8* pMatch = &m_dict[next_match_pos & m_max_dict_size_mask];
if ((pCur[0] == pMatch[0]) && (pCur[1] == pMatch[1]))
return match_dist;
return 0;
}
bool search_accelerator::find_all_matches(uint num_bytes)
{
if (!m_matches.try_resize_no_construct(m_max_probes * num_bytes))
return false;
if (!m_match_refs.try_resize_no_construct(num_bytes))
return false;
memset(m_match_refs.get_ptr(), 0xFF, m_match_refs.size_in_bytes());
m_fill_lookahead_pos = m_lookahead_pos;
m_fill_lookahead_size = num_bytes;
m_fill_dict_size = m_cur_dict_size;
m_next_match_ref = 0;
if (!m_pTask_pool)
{
find_all_matches_callback(0, NULL);
m_num_completed_helper_threads = 0;
}
else
{
if (!m_hash_thread_index.try_resize_no_construct(0x10000))
return false;
memset(m_hash_thread_index.get_ptr(), 0xFF, m_hash_thread_index.size_in_bytes());
uint next_thread_index = 0;
const uint8* pDict = &m_dict[m_lookahead_pos & m_max_dict_size_mask];
uint num_unique_trigrams = 0;
if (num_bytes >= 3)
{
uint c0 = pDict[0];
uint c1 = pDict[1];
const int limit = ((int)num_bytes - 2);
for (int i = 0; i < limit; i++)
{
uint c2 = pDict[2];
uint t = hash3_to_16(c0, c1, c2);
c0 = c1;
c1 = c2;
pDict++;
if (m_hash_thread_index[t] == UINT8_MAX)
{
num_unique_trigrams++;
m_hash_thread_index[t] = static_cast<uint8>(next_thread_index);
if (++next_thread_index == m_max_helper_threads)
next_thread_index = 0;
}
}
}
m_num_completed_helper_threads = 0;
if (!m_pTask_pool->queue_multiple_object_tasks(this, &search_accelerator::find_all_matches_callback, 0, m_max_helper_threads))
return false;
}
return find_len2_matches();
}
bool search_accelerator::add_bytes_begin(uint num_bytes, const uint8* pBytes)
{
LZHAM_ASSERT(num_bytes <= m_max_dict_size);
LZHAM_ASSERT(!m_lookahead_size);
uint add_pos = m_lookahead_pos & m_max_dict_size_mask;
LZHAM_ASSERT((add_pos + num_bytes) <= m_max_dict_size);
memcpy(&m_dict[add_pos], pBytes, num_bytes);
uint dict_bytes_to_mirror = LZHAM_MIN(static_cast<uint>(CLZBase::cMaxHugeMatchLen), m_max_dict_size);
if (add_pos < dict_bytes_to_mirror)
memcpy(&m_dict[m_max_dict_size], &m_dict[0], dict_bytes_to_mirror);
m_lookahead_size = num_bytes;
uint max_possible_dict_size = m_max_dict_size - num_bytes;
m_cur_dict_size = LZHAM_MIN(m_cur_dict_size, max_possible_dict_size);
m_next_match_ref = 0;
return find_all_matches(num_bytes);
}
void search_accelerator::add_bytes_end()
{
if (m_pTask_pool)
{
m_pTask_pool->join();
}
LZHAM_ASSERT((uint)m_next_match_ref <= m_matches.size());
}
dict_match* search_accelerator::find_matches(uint lookahead_ofs, bool spin)
{
LZHAM_ASSERT(lookahead_ofs < m_lookahead_size);
const uint match_ref_ofs = static_cast<uint>(m_lookahead_pos - m_fill_lookahead_pos + lookahead_ofs);
int match_ref;
uint spin_count = 0;
// This may spin until the match finder job(s) catch up to the caller's lookahead position.
for ( ; ; )
{
match_ref = m_match_refs[match_ref_ofs];
if (match_ref == -2)
return NULL;
else if (match_ref != -1)
break;
spin_count++;
const uint cMaxSpinCount = 1000;
if ((spin) && (spin_count < cMaxSpinCount))
{
lzham_yield_processor();
lzham_yield_processor();
lzham_yield_processor();
lzham_yield_processor();
lzham_yield_processor();
lzham_yield_processor();
lzham_yield_processor();
lzham_yield_processor();
LZHAM_MEMORY_IMPORT_BARRIER
}
else
{
spin_count = cMaxSpinCount;
lzham_sleep(1);
}
}
LZHAM_MEMORY_IMPORT_BARRIER
return &m_matches[match_ref];
}
void search_accelerator::advance_bytes(uint num_bytes)
{
LZHAM_ASSERT(num_bytes <= m_lookahead_size);
m_lookahead_pos += num_bytes;
m_lookahead_size -= num_bytes;
m_cur_dict_size += num_bytes;
LZHAM_ASSERT(m_cur_dict_size <= m_max_dict_size);
}
}

272
r5dev/thirdparty/lzham/lzham_mem.cpp vendored Normal file
View File

@ -0,0 +1,272 @@
// File: lzham_mem.cpp
// See Copyright Notice and license at the end of include/lzham.h
#include "include/lzham_core.h"
#include <stdio.h>
#include <stdint.h>
#include <malloc.h>
using namespace lzham;
#define LZHAM_MEM_STATS 0
#ifndef LZHAM_USE_WIN32_API
//#define _msize malloc_usable_size
#endif
namespace lzham
{
#if LZHAM_64BIT_POINTERS
const uint64 MAX_POSSIBLE_BLOCK_SIZE = 0x400000000ULL;
#else
const uint32 MAX_POSSIBLE_BLOCK_SIZE = 0x7FFF0000U;
#endif
#if LZHAM_MEM_STATS
#if LZHAM_64BIT_POINTERS
typedef atomic64_t mem_stat_t;
#define LZHAM_MEM_COMPARE_EXCHANGE atomic_compare_exchange64
#else
typedef atomic32_t mem_stat_t;
#define LZHAM_MEM_COMPARE_EXCHANGE atomic_compare_exchange32
#endif
static volatile atomic32_t g_total_blocks;
static volatile mem_stat_t g_total_allocated;
static volatile mem_stat_t g_max_allocated;
static mem_stat_t update_total_allocated(int block_delta, mem_stat_t byte_delta)
{
atomic32_t cur_total_blocks;
for ( ; ; )
{
cur_total_blocks = g_total_blocks;
atomic32_t new_total_blocks = static_cast<atomic32_t>(cur_total_blocks + block_delta);
LZHAM_ASSERT(new_total_blocks >= 0);
if (atomic_compare_exchange32(&g_total_blocks, new_total_blocks, cur_total_blocks) == cur_total_blocks)
break;
}
mem_stat_t cur_total_allocated, new_total_allocated;
for ( ; ; )
{
cur_total_allocated = g_total_allocated;
new_total_allocated = static_cast<mem_stat_t>(cur_total_allocated + byte_delta);
LZHAM_ASSERT(new_total_allocated >= 0);
if (LZHAM_MEM_COMPARE_EXCHANGE(&g_total_allocated, new_total_allocated, cur_total_allocated) == cur_total_allocated)
break;
}
for ( ; ; )
{
mem_stat_t cur_max_allocated = g_max_allocated;
mem_stat_t new_max_allocated = LZHAM_MAX(new_total_allocated, cur_max_allocated);
if (LZHAM_MEM_COMPARE_EXCHANGE(&g_max_allocated, new_max_allocated, cur_max_allocated) == cur_max_allocated)
break;
}
return new_total_allocated;
}
#endif // LZHAM_MEM_STATS
static void* lzham_default_realloc(void* p, size_t size, size_t* pActual_size, lzham_bool movable, void* pUser_data)
{
LZHAM_NOTE_UNUSED(pUser_data);
void* p_new;
if (!p)
{
p_new = malloc(size);
LZHAM_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0 );
if (pActual_size)
*pActual_size = p_new ? _msize(p_new) : 0;
}
else if (!size)
{
free(p);
p_new = NULL;
if (pActual_size)
*pActual_size = 0;
}
else
{
void* p_final_block = p;
#ifdef WIN32
p_new = _expand(p, size);
#else
p_new = NULL;
#endif
if (p_new)
{
LZHAM_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0 );
p_final_block = p_new;
}
else if (movable)
{
p_new = realloc(p, size);
if (p_new)
{
LZHAM_ASSERT( (reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0 );
p_final_block = p_new;
}
}
if (pActual_size)
*pActual_size = _msize(p_final_block);
}
return p_new;
}
static size_t lzham_default_msize(void* p, void* pUser_data)
{
LZHAM_NOTE_UNUSED(pUser_data);
return p ? _msize(p) : 0;
}
static lzham_realloc_func g_pRealloc = lzham_default_realloc;
static lzham_msize_func g_pMSize = lzham_default_msize;
static void* g_pUser_data;
static inline void lzham_mem_error(const char* p_msg)
{
lzham_assert(p_msg, __FILE__, __LINE__);
}
void* lzham_malloc(size_t size, size_t* pActual_size)
{
size = (size + sizeof(uint32) - 1U) & ~(sizeof(uint32) - 1U);
if (!size)
size = sizeof(uint32);
if (size > MAX_POSSIBLE_BLOCK_SIZE)
{
lzham_mem_error("lzham_malloc: size too big");
return NULL;
}
size_t actual_size = size;
uint8* p_new = static_cast<uint8*>((*g_pRealloc)(NULL, size, &actual_size, true, g_pUser_data));
if (pActual_size)
*pActual_size = actual_size;
if ((!p_new) || (actual_size < size))
{
lzham_mem_error("lzham_malloc: out of memory");
return NULL;
}
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0);
#if LZHAM_MEM_STATS
update_total_allocated(1, static_cast<mem_stat_t>(actual_size));
#endif
return p_new;
}
void* lzham_realloc(void* p, size_t size, size_t* pActual_size, bool movable)
{
if ((ptr_bits_t)p & (LZHAM_MIN_ALLOC_ALIGNMENT - 1))
{
lzham_mem_error("lzham_realloc: bad ptr");
return NULL;
}
if (size > MAX_POSSIBLE_BLOCK_SIZE)
{
lzham_mem_error("lzham_malloc: size too big");
return NULL;
}
#if LZHAM_MEM_STATS
size_t cur_size = p ? (*g_pMSize)(p, g_pUser_data) : 0;
#endif
size_t actual_size = size;
void* p_new = (*g_pRealloc)(p, size, &actual_size, movable, g_pUser_data);
if (pActual_size)
*pActual_size = actual_size;
LZHAM_ASSERT((reinterpret_cast<ptr_bits_t>(p_new) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1)) == 0);
#if LZHAM_MEM_STATS
int num_new_blocks = 0;
if (p)
{
if (!p_new)
num_new_blocks = -1;
}
else if (p_new)
{
num_new_blocks = 1;
}
update_total_allocated(num_new_blocks, static_cast<mem_stat_t>(actual_size) - static_cast<mem_stat_t>(cur_size));
#endif
return p_new;
}
void lzham_free(void* p)
{
if (!p)
return;
if (reinterpret_cast<ptr_bits_t>(p) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1))
{
lzham_mem_error("lzham_free: bad ptr");
return;
}
#if LZHAM_MEM_STATS
size_t cur_size = (*g_pMSize)(p, g_pUser_data);
update_total_allocated(-1, -static_cast<mem_stat_t>(cur_size));
#endif
(*g_pRealloc)(p, 0, NULL, true, g_pUser_data);
}
size_t lzham_msize(void* p)
{
if (!p)
return 0;
if (reinterpret_cast<ptr_bits_t>(p) & (LZHAM_MIN_ALLOC_ALIGNMENT - 1))
{
lzham_mem_error("lzham_msize: bad ptr");
return 0;
}
return (*g_pMSize)(p, g_pUser_data);
}
void LZHAM_CDECL lzham_lib_set_memory_callbacks(lzham_realloc_func pRealloc, lzham_msize_func pMSize, void* pUser_data)
{
if ((!pRealloc) || (!pMSize))
{
g_pRealloc = lzham_default_realloc;
g_pMSize = lzham_default_msize;
g_pUser_data = NULL;
}
else
{
g_pRealloc = pRealloc;
g_pMSize = pMSize;
g_pUser_data = pUser_data;
}
}
void lzham_print_mem_stats()
{
#if LZHAM_MEM_STATS
printf("Current blocks: %u, allocated: %I64u, max ever allocated: %I64i\n", g_total_blocks, (int64)g_total_allocated, (int64)g_max_allocated);
#endif
}
} // namespace lzham

View File

@ -0,0 +1,146 @@
// File: platform.cpp
// See Copyright Notice and license at the end of include/lzham.h
#include "include/lzham_core.h"
#include "include/lzham_timer.h"
#if LZHAM_PLATFORM_X360
#include <xbdm.h>
#endif
#ifndef _MSC_VER
int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...)
{
if (!sizeOfBuffer)
return 0;
va_list args;
va_start(args, format);
int c = vsnprintf(buffer, sizeOfBuffer, format, args);
va_end(args);
buffer[sizeOfBuffer - 1] = '\0';
if (c < 0)
return sizeOfBuffer - 1;
return LZHAM_MIN(c, (int)sizeOfBuffer - 1);
}
int vsprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, va_list args)
{
if (!sizeOfBuffer)
return 0;
int c = vsnprintf(buffer, sizeOfBuffer, format, args);
buffer[sizeOfBuffer - 1] = '\0';
if (c < 0)
return sizeOfBuffer - 1;
return LZHAM_MIN(c, (int)sizeOfBuffer - 1);
}
#endif // __GNUC__
bool lzham_is_debugger_present(void)
{
#if LZHAM_PLATFORM_X360
return DmIsDebuggerPresent() != 0;
#elif LZHAM_USE_WIN32_API
return IsDebuggerPresent() != 0;
#else
return false;
#endif
}
void lzham_debug_break(void)
{
#if LZHAM_USE_WIN32_API
DebugBreak();
#endif
}
void lzham_output_debug_string(const char* p)
{
LZHAM_NOTE_UNUSED(p);
#if LZHAM_USE_WIN32_API
OutputDebugStringA(p);
#endif
}
#if LZHAM_BUFFERED_PRINTF
// This stuff was a quick hack only intended for debugging/development.
namespace lzham
{
struct buffered_str
{
enum { cBufSize = 256 };
char m_buf[cBufSize];
};
static lzham::vector<buffered_str> g_buffered_strings;
static volatile long g_buffered_string_locked;
static void lock_buffered_strings()
{
while (atomic_exchange32(&g_buffered_string_locked, 1) == 1)
{
lzham_yield_processor();
lzham_yield_processor();
lzham_yield_processor();
lzham_yield_processor();
}
LZHAM_MEMORY_IMPORT_BARRIER
}
static void unlock_buffered_strings()
{
LZHAM_MEMORY_EXPORT_BARRIER
atomic_exchange32(&g_buffered_string_locked, 0);
}
} // namespace lzham
void lzham_buffered_printf(const char *format, ...)
{
format;
char buf[lzham::buffered_str::cBufSize];
va_list args;
va_start(args, format);
vsnprintf_s(buf, sizeof(buf), sizeof(buf), format, args);
va_end(args);
buf[sizeof(buf) - 1] = '\0';
lzham::lock_buffered_strings();
if (!lzham::g_buffered_strings.capacity())
{
lzham::g_buffered_strings.try_reserve(2048);
}
if (lzham::g_buffered_strings.try_resize(lzham::g_buffered_strings.size() + 1))
{
memcpy(lzham::g_buffered_strings.back().m_buf, buf, sizeof(buf));
}
lzham::unlock_buffered_strings();
}
void lzham_flush_buffered_printf()
{
lzham::lock_buffered_strings();
for (lzham::uint i = 0; i < lzham::g_buffered_strings.size(); i++)
{
printf("%s", lzham::g_buffered_strings[i].m_buf);
}
lzham::g_buffered_strings.try_resize(0);
lzham::unlock_buffered_strings();
}
#endif

View File

@ -0,0 +1,414 @@
// File: polar_codes.cpp
// See Copyright Notice and license at the end of include/lzham.h
//
// Andrew Polar's prefix code algorithm:
// http://ezcodesample.com/prefixer/prefixer_article.html
//
// Also implements Fyffe's approximate codelength generation method, which is
// very similar but operates directly on codelengths vs. symbol frequencies:
// Fyffe Codes for Fast Codelength Approximation, Graham Fyffe, 1999
// http://code.google.com/p/lzham/wiki/FyffeCodes
#include "include/lzham_core.h"
#include "include/lzham_polar_codes.h"
#define LZHAM_USE_SHANNON_FANO_CODES 0
#define LZHAM_USE_FYFFE_CODES 0
namespace lzham
{
struct sym_freq
{
uint16 m_freq;
uint16 m_sym;
};
static inline sym_freq* radix_sort_syms(uint num_syms, sym_freq* syms0, sym_freq* syms1)
{
const uint cMaxPasses = 2;
uint hist[256 * cMaxPasses];
memset(hist, 0, sizeof(hist[0]) * 256 * cMaxPasses);
{
sym_freq* p = syms0;
sym_freq* q = syms0 + (num_syms >> 1) * 2;
for ( ; p != q; p += 2)
{
const uint freq0 = p[0].m_freq;
const uint freq1 = p[1].m_freq;
hist[ freq0 & 0xFF]++;
hist[256 + ((freq0 >> 8) & 0xFF)]++;
hist[ freq1 & 0xFF]++;
hist[256 + ((freq1 >> 8) & 0xFF)]++;
}
if (num_syms & 1)
{
const uint freq = p->m_freq;
hist[ freq & 0xFF]++;
hist[256 + ((freq >> 8) & 0xFF)]++;
}
}
sym_freq* pCur_syms = syms0;
sym_freq* pNew_syms = syms1;
const uint total_passes = (hist[256] == num_syms) ? 1 : cMaxPasses;
for (uint pass = 0; pass < total_passes; pass++)
{
const uint* pHist = &hist[pass << 8];
uint offsets[256];
uint cur_ofs = 0;
for (uint i = 0; i < 256; i += 2)
{
offsets[i] = cur_ofs;
cur_ofs += pHist[i];
offsets[i+1] = cur_ofs;
cur_ofs += pHist[i+1];
}
const uint pass_shift = pass << 3;
sym_freq* p = pCur_syms;
sym_freq* q = pCur_syms + (num_syms >> 1) * 2;
for ( ; p != q; p += 2)
{
uint c0 = p[0].m_freq;
uint c1 = p[1].m_freq;
if (pass)
{
c0 >>= 8;
c1 >>= 8;
}
c0 &= 0xFF;
c1 &= 0xFF;
// Cut down on LHS's on console platforms by processing two at a time.
if (c0 == c1)
{
uint dst_offset0 = offsets[c0];
offsets[c0] = dst_offset0 + 2;
pNew_syms[dst_offset0] = p[0];
pNew_syms[dst_offset0 + 1] = p[1];
}
else
{
uint dst_offset0 = offsets[c0]++;
uint dst_offset1 = offsets[c1]++;
pNew_syms[dst_offset0] = p[0];
pNew_syms[dst_offset1] = p[1];
}
}
if (num_syms & 1)
{
uint c = ((p->m_freq) >> pass_shift) & 0xFF;
uint dst_offset = offsets[c];
offsets[c] = dst_offset + 1;
pNew_syms[dst_offset] = *p;
}
sym_freq* t = pCur_syms;
pCur_syms = pNew_syms;
pNew_syms = t;
}
#if LZHAM_ASSERTS_ENABLED
uint prev_freq = 0;
for (uint i = 0; i < num_syms; i++)
{
LZHAM_ASSERT(!(pCur_syms[i].m_freq < prev_freq));
prev_freq = pCur_syms[i].m_freq;
}
#endif
return pCur_syms;
}
struct polar_work_tables
{
sym_freq syms0[cPolarMaxSupportedSyms];
sym_freq syms1[cPolarMaxSupportedSyms];
};
uint get_generate_polar_codes_table_size()
{
return sizeof(polar_work_tables);
}
void generate_polar_codes(uint num_syms, sym_freq* pSF, uint8* pCodesizes, uint& max_code_size_ret)
{
int tmp_freq[cPolarMaxSupportedSyms];
uint orig_total_freq = 0;
uint cur_total = 0;
for (uint i = 0; i < num_syms; i++)
{
uint sym_freq = pSF[num_syms - 1 - i].m_freq;
orig_total_freq += sym_freq;
uint sym_len = math::total_bits(sym_freq);
uint adjusted_sym_freq = 1 << (sym_len - 1);
tmp_freq[i] = adjusted_sym_freq;
cur_total += adjusted_sym_freq;
}
uint tree_total = 1 << (math::total_bits(orig_total_freq) - 1);
if (tree_total < orig_total_freq)
tree_total <<= 1;
uint start_index = 0;
while ((cur_total < tree_total) && (start_index < num_syms))
{
for (uint i = start_index; i < num_syms; i++)
{
uint freq = tmp_freq[i];
if ((cur_total + freq) <= tree_total)
{
tmp_freq[i] += freq;
if ((cur_total += freq) == tree_total)
break;
}
else
{
start_index = i + 1;
}
}
}
LZHAM_ASSERT(cur_total == tree_total);
uint max_code_size = 0;
const uint tree_total_bits = math::total_bits(tree_total);
for (uint i = 0; i < num_syms; i++)
{
uint codesize = (tree_total_bits - math::total_bits(tmp_freq[i]));
max_code_size = LZHAM_MAX(codesize, max_code_size);
pCodesizes[pSF[num_syms-1-i].m_sym] = static_cast<uint8>(codesize);
}
max_code_size_ret = max_code_size;
}
#if LZHAM_USE_FYFFE_CODES
void generate_fyffe_codes(uint num_syms, sym_freq* pSF, uint8* pCodesizes, uint& max_code_size_ret)
{
int tmp_codesizes[cPolarMaxSupportedSyms];
uint cur_total = 0;
uint orig_total = 0;
for (uint i = 0; i < num_syms; i++)
{
uint sym_freq = pSF[i].m_freq;
orig_total += sym_freq;
// Compute the nearest power of 2 lower or equal to the symbol's frequency.
// This is equivalent to codesize=ceil(-log2(sym_prob)).
uint floor_sym_freq = sym_freq;
if (!math::is_power_of_2(floor_sym_freq))
{
uint sym_freq_bits = math::total_bits(sym_freq);
floor_sym_freq = 1 << (sym_freq_bits - 1);
}
// Compute preliminary codesizes. tmp_freq's will always be <= the input frequencies.
tmp_codesizes[i] = math::total_bits(floor_sym_freq);
cur_total += floor_sym_freq;
}
// Desired_total is a power of 2, and will always be >= the adjusted frequency total.
uint desired_total = cur_total;
if (!math::is_power_of_2(desired_total))
desired_total = math::next_pow2(desired_total);
LZHAM_ASSERT(cur_total <= desired_total);
// Compute residual and initial symbol codesizes.
uint desired_total_bits = math::total_bits(desired_total);
int r = desired_total;
for (uint i = 0; i < num_syms; i++)
{
uint codesize = desired_total_bits - tmp_codesizes[i];
tmp_codesizes[i] = static_cast<uint8>(codesize);
r -= (desired_total >> codesize);
}
LZHAM_ASSERT(r >= 0);
int sym_freq_scale = (desired_total << 7) / orig_total;
// Promote codesizes from most probable to lowest, as needed.
bool force_unhappiness = false;
while (r > 0)
{
for (int i = num_syms - 1; i >= 0; i--)
{
uint codesize = tmp_codesizes[i];
if (codesize == 1)
continue;
int sym_freq = pSF[i].m_freq;
int f = desired_total >> codesize;
if (f > r)
continue;
// A code is "unhappy" when it is assigned more bits than -log2(sym_prob).
// It's too expensive to compute -log2(sym_freq/total_freq), so instead this directly compares the symbol's original
// frequency vs. the effective/adjusted frequency. sym_freq >= f is an approximation.
//bool unhappy = force_unhappiness || (sym_freq >= f);
// Compare the symbol's original probability vs. its effective probability at its current codelength.
//bool unhappy = force_unhappiness || ((sym_freq * ((float)desired_total / orig_total)) > f);
bool unhappy = force_unhappiness || ((sym_freq * sym_freq_scale) > (f << 7));
if (unhappy)
{
tmp_codesizes[i]--;
r -= f;
if (r <= 0)
break;
}
}
// Occasionally, a second pass is required to reduce the residual to 0.
// Subsequent passes ignore unhappiness. This is not discussed in Fyffe's original article.
force_unhappiness = true;
}
LZHAM_ASSERT(!r);
uint max_code_size = 0;
for (uint i = 0; i < num_syms; i++)
{
uint codesize = tmp_codesizes[i];
max_code_size = LZHAM_MAX(codesize, max_code_size);
pCodesizes[pSF[i].m_sym] = static_cast<uint8>(codesize);
}
max_code_size_ret = max_code_size;
}
#endif //LZHAM_USE_FYFFE_CODES
#if LZHAM_USE_SHANNON_FANO_CODES
// Straightforward recursive Shannon-Fano implementation, for comparison purposes.
static void generate_shannon_fano_codes_internal(uint num_syms, sym_freq* pSF, uint8* pCodesizes, int l, int h, uint total_freq)
{
LZHAM_ASSERT((h - l) >= 2);
uint left_total = total_freq;
uint right_total = 0;
int best_diff = INT_MAX;
int best_split_index = 0;
for (int i = h - 1; i > l; i--)
{
uint freq = pSF[i].m_freq;
uint next_left_total = left_total - freq;
uint next_right_total = right_total + freq;
LZHAM_ASSERT((next_left_total + next_right_total) == total_freq);
int diff = labs(next_left_total - next_right_total);
if (diff >= best_diff)
break;
left_total = next_left_total;
right_total = next_right_total;
best_split_index = i;
best_diff = diff;
if (!best_diff)
break;
}
for (int i = l; i < h; i++)
pCodesizes[i]++;
if ((best_split_index - l) > 1) generate_shannon_fano_codes_internal(num_syms, pSF, pCodesizes, l, best_split_index, left_total);
if ((h - best_split_index) > 1) generate_shannon_fano_codes_internal(num_syms, pSF, pCodesizes, best_split_index, h, right_total);
}
void generate_shannon_fano_codes(uint num_syms, sym_freq* pSF, uint total_freq, uint8* pCodesizes, uint& max_code_size_ret)
{
LZHAM_ASSERT(num_syms >= 2);
uint8 tmp_codesizes[cPolarMaxSupportedSyms];
memset(tmp_codesizes, 0, num_syms);
generate_shannon_fano_codes_internal(num_syms, pSF, tmp_codesizes, 0, num_syms, total_freq);
uint max_code_size = 0;
for (uint i = 0; i < num_syms; i++)
{
uint codesize = tmp_codesizes[i];
max_code_size = LZHAM_MAX(codesize, max_code_size);
pCodesizes[pSF[i].m_sym] = static_cast<uint8>(codesize);
}
max_code_size_ret = max_code_size;
}
#endif // LZHAM_USE_SHANNON_FANO_CODES
bool generate_polar_codes(void* pContext, uint num_syms, const uint16* pFreq, uint8* pCodesizes, uint& max_code_size, uint& total_freq_ret)
{
if ((!num_syms) || (num_syms > cPolarMaxSupportedSyms))
return false;
polar_work_tables& state = *static_cast<polar_work_tables*>(pContext);;
uint max_freq = 0;
uint total_freq = 0;
uint num_used_syms = 0;
for (uint i = 0; i < num_syms; i++)
{
uint freq = pFreq[i];
if (!freq)
pCodesizes[i] = 0;
else
{
total_freq += freq;
max_freq = math::maximum(max_freq, freq);
sym_freq& sf = state.syms0[num_used_syms];
sf.m_sym = static_cast<uint16>(i);
sf.m_freq = static_cast<uint16>(freq);
num_used_syms++;
}
}
total_freq_ret = total_freq;
if (num_used_syms == 1)
{
pCodesizes[state.syms0[0].m_sym] = 1;
}
else
{
sym_freq* syms = radix_sort_syms(num_used_syms, state.syms0, state.syms1);
#if LZHAM_USE_SHANNON_FANO_CODES
generate_shannon_fano_codes(num_syms, syms, total_freq, pCodesizes, max_code_size);
#elif LZHAM_USE_FYFFE_CODES
generate_fyffe_codes(num_syms, syms, pCodesizes, max_code_size);
#else
generate_polar_codes(num_syms, syms, pCodesizes, max_code_size);
#endif
}
return true;
}
} // namespace lzham

View File

@ -0,0 +1,350 @@
// File: lzham_prefix_coding.cpp
// See Copyright Notice and license at the end of include/lzham.h
#include "include/lzham_core.h"
#include "include/lzham_prefix_coding.h"
#ifdef LZHAM_BUILD_DEBUG
//#define TEST_DECODER_TABLES
#endif
namespace lzham
{
namespace prefix_coding
{
bool limit_max_code_size(uint num_syms, uint8* pCodesizes, uint max_code_size)
{
const uint cMaxEverCodeSize = 34;
if ((!num_syms) || (num_syms > cMaxSupportedSyms) || (max_code_size < 1) || (max_code_size > cMaxEverCodeSize))
return false;
uint num_codes[cMaxEverCodeSize + 1];
utils::zero_object(num_codes);
bool should_limit = false;
for (uint i = 0; i < num_syms; i++)
{
uint c = pCodesizes[i];
LZHAM_ASSERT(c <= cMaxEverCodeSize);
num_codes[c]++;
if (c > max_code_size)
should_limit = true;
}
if (!should_limit)
return true;
uint ofs = 0;
uint next_sorted_ofs[cMaxEverCodeSize + 1];
for (uint i = 1; i <= cMaxEverCodeSize; i++)
{
next_sorted_ofs[i] = ofs;
ofs += num_codes[i];
}
if ((ofs < 2) || (ofs > cMaxSupportedSyms))
return true;
if (ofs > (1U << max_code_size))
return false;
for (uint i = max_code_size + 1; i <= cMaxEverCodeSize; i++)
num_codes[max_code_size] += num_codes[i];
// Technique of adjusting tree to enforce maximum code size from LHArc.
uint total = 0;
for (uint i = max_code_size; i; --i)
total += (num_codes[i] << (max_code_size - i));
if (total == (1U << max_code_size))
return true;
do
{
num_codes[max_code_size]--;
uint i;
for (i = max_code_size - 1; i; --i)
{
if (!num_codes[i])
continue;
num_codes[i]--;
num_codes[i + 1] += 2;
break;
}
if (!i)
return false;
total--;
} while (total != (1U << max_code_size));
uint8 new_codesizes[cMaxSupportedSyms];
uint8* p = new_codesizes;
for (uint i = 1; i <= max_code_size; i++)
{
uint n = num_codes[i];
if (n)
{
memset(p, i, n);
p += n;
}
}
for (uint i = 0; i < num_syms; i++)
{
const uint c = pCodesizes[i];
if (c)
{
uint next_ofs = next_sorted_ofs[c];
next_sorted_ofs[c] = next_ofs + 1;
pCodesizes[i] = static_cast<uint8>(new_codesizes[next_ofs]);
}
}
return true;
}
bool generate_codes(uint num_syms, const uint8* pCodesizes, uint16* pCodes)
{
uint num_codes[cMaxExpectedCodeSize + 1];
utils::zero_object(num_codes);
for (uint i = 0; i < num_syms; i++)
{
uint c = pCodesizes[i];
LZHAM_ASSERT(c <= cMaxExpectedCodeSize);
num_codes[c]++;
}
uint code = 0;
uint next_code[cMaxExpectedCodeSize + 1];
next_code[0] = 0;
for (uint i = 1; i <= cMaxExpectedCodeSize; i++)
{
next_code[i] = code;
code = (code + num_codes[i]) << 1;
}
if (code != (1 << (cMaxExpectedCodeSize + 1)))
{
uint t = 0;
for (uint i = 1; i <= cMaxExpectedCodeSize; i++)
{
t += num_codes[i];
if (t > 1)
return false;
}
}
for (uint i = 0; i < num_syms; i++)
{
uint c = pCodesizes[i];
LZHAM_ASSERT(!c || (next_code[c] <= UINT16_MAX));
pCodes[i] = static_cast<uint16>(next_code[c]++);
LZHAM_ASSERT(!c || (math::total_bits(pCodes[i]) <= pCodesizes[i]));
}
return true;
}
bool generate_decoder_tables(uint num_syms, const uint8* pCodesizes, decoder_tables* pTables, uint table_bits)
{
uint min_codes[cMaxExpectedCodeSize];
if ((!num_syms) || (table_bits > cMaxTableBits))
return false;
pTables->m_num_syms = num_syms;
uint num_codes[cMaxExpectedCodeSize + 1];
utils::zero_object(num_codes);
for (uint i = 0; i < num_syms; i++)
{
uint c = pCodesizes[i];
num_codes[c]++;
}
uint sorted_positions[cMaxExpectedCodeSize + 1];
uint next_code = 0;
uint total_used_syms = 0;
uint max_code_size = 0;
uint min_code_size = UINT_MAX;
for (uint i = 1; i <= cMaxExpectedCodeSize; i++)
{
const uint n = num_codes[i];
if (!n)
pTables->m_max_codes[i - 1] = 0;//UINT_MAX;
else
{
min_code_size = math::minimum(min_code_size, i);
max_code_size = math::maximum(max_code_size, i);
min_codes[i - 1] = next_code;
pTables->m_max_codes[i - 1] = next_code + n - 1;
pTables->m_max_codes[i - 1] = 1 + ((pTables->m_max_codes[i - 1] << (16 - i)) | ((1 << (16 - i)) - 1));
pTables->m_val_ptrs[i - 1] = total_used_syms;
sorted_positions[i] = total_used_syms;
next_code += n;
total_used_syms += n;
}
next_code <<= 1;
}
pTables->m_total_used_syms = total_used_syms;
if (total_used_syms > pTables->m_cur_sorted_symbol_order_size)
{
pTables->m_cur_sorted_symbol_order_size = total_used_syms;
if (!math::is_power_of_2(total_used_syms))
pTables->m_cur_sorted_symbol_order_size = math::minimum<uint>(num_syms, math::next_pow2(total_used_syms));
if (pTables->m_sorted_symbol_order)
{
lzham_delete_array(pTables->m_sorted_symbol_order);
pTables->m_sorted_symbol_order = NULL;
}
pTables->m_sorted_symbol_order = lzham_new_array<uint16>(pTables->m_cur_sorted_symbol_order_size);
if (!pTables->m_sorted_symbol_order)
return false;
}
pTables->m_min_code_size = static_cast<uint8>(min_code_size);
pTables->m_max_code_size = static_cast<uint8>(max_code_size);
for (uint i = 0; i < num_syms; i++)
{
uint c = pCodesizes[i];
if (c)
{
LZHAM_ASSERT(num_codes[c]);
uint sorted_pos = sorted_positions[c]++;
LZHAM_ASSERT(sorted_pos < total_used_syms);
pTables->m_sorted_symbol_order[sorted_pos] = static_cast<uint16>(i);
}
}
if (table_bits <= pTables->m_min_code_size)
table_bits = 0;
pTables->m_table_bits = table_bits;
if (table_bits)
{
uint table_size = 1 << table_bits;
if (table_size > pTables->m_cur_lookup_size)
{
pTables->m_cur_lookup_size = table_size;
if (pTables->m_lookup)
{
lzham_delete_array(pTables->m_lookup);
pTables->m_lookup = NULL;
}
pTables->m_lookup = lzham_new_array<uint32>(table_size);
if (!pTables->m_lookup)
return false;
}
memset(pTables->m_lookup, 0xFF, static_cast<uint>(sizeof(pTables->m_lookup[0])) * (1UL << table_bits));
for (uint codesize = 1; codesize <= table_bits; codesize++)
{
if (!num_codes[codesize])
continue;
const uint fillsize = table_bits - codesize;
const uint fillnum = 1 << fillsize;
const uint min_code = min_codes[codesize - 1];
const uint max_code = pTables->get_unshifted_max_code(codesize);
const uint val_ptr = pTables->m_val_ptrs[codesize - 1];
for (uint code = min_code; code <= max_code; code++)
{
const uint sym_index = pTables->m_sorted_symbol_order[ val_ptr + code - min_code ];
LZHAM_ASSERT( pCodesizes[sym_index] == codesize );
for (uint j = 0; j < fillnum; j++)
{
const uint t = j + (code << fillsize);
LZHAM_ASSERT(t < (1U << table_bits));
LZHAM_ASSERT(pTables->m_lookup[t] == UINT32_MAX);
pTables->m_lookup[t] = sym_index | (codesize << 16U);
}
}
}
}
for (uint i = 0; i < cMaxExpectedCodeSize; i++)
pTables->m_val_ptrs[i] -= min_codes[i];
pTables->m_table_max_code = 0;
pTables->m_decode_start_code_size = pTables->m_min_code_size;
if (table_bits)
{
uint i;
for (i = table_bits; i >= 1; i--)
{
if (num_codes[i])
{
pTables->m_table_max_code = pTables->m_max_codes[i - 1];
break;
}
}
if (i >= 1)
{
pTables->m_decode_start_code_size = table_bits + 1;
for (i = table_bits + 1; i <= max_code_size; i++)
{
if (num_codes[i])
{
pTables->m_decode_start_code_size = i;
break;
}
}
}
}
// sentinels
pTables->m_max_codes[cMaxExpectedCodeSize] = UINT_MAX;
pTables->m_val_ptrs[cMaxExpectedCodeSize] = 0xFFFFF;
pTables->m_table_shift = 32 - pTables->m_table_bits;
return true;
}
} // namespace prefix_codig
} // namespace lzham

View File

@ -0,0 +1,227 @@
// File: lzham_task_pool_pthreads.cpp
//
// Copyright (c) 2009-2010 Richard Geldreich, Jr. <richgel99@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "include/lzham_core.h"
#include "include/lzham_pthreads_threading.h"
#include "include/lzham_timer.h"
#ifdef WIN32
#include <process.h>
#endif
#if defined(__GNUC__)
#include <sys/sysinfo.h>
#endif
#if LZHAM_USE_PTHREADS_API
#ifdef WIN32
#pragma comment(lib, "../ext/libpthread/lib/pthreadVC2.lib")
#endif
namespace lzham
{
task_pool::task_pool() :
m_num_threads(0),
m_tasks_available(0, 32767),
m_num_outstanding_tasks(0),
m_exit_flag(false)
{
utils::zero_object(m_threads);
}
task_pool::task_pool(uint num_threads) :
m_num_threads(0),
m_tasks_available(0, 32767),
m_num_outstanding_tasks(0),
m_exit_flag(false)
{
utils::zero_object(m_threads);
bool status = init(num_threads);
LZHAM_VERIFY(status);
}
task_pool::~task_pool()
{
deinit();
}
bool task_pool::init(uint num_threads)
{
LZHAM_ASSERT(num_threads <= cMaxThreads);
num_threads = math::minimum<uint>(num_threads, cMaxThreads);
deinit();
bool succeeded = true;
m_num_threads = 0;
while (m_num_threads < num_threads)
{
int status = pthread_create(&m_threads[m_num_threads], NULL, thread_func, this);
if (status)
{
succeeded = false;
break;
}
m_num_threads++;
}
if (!succeeded)
{
deinit();
return false;
}
return true;
}
void task_pool::deinit()
{
if (m_num_threads)
{
join();
atomic_exchange32(&m_exit_flag, true);
m_tasks_available.release(m_num_threads);
for (uint i = 0; i < m_num_threads; i++)
pthread_join(m_threads[i], NULL);
m_num_threads = 0;
atomic_exchange32(&m_exit_flag, false);
}
m_task_stack.clear();
m_num_outstanding_tasks = 0;
}
bool task_pool::queue_task(task_callback_func pFunc, uint64 data, void* pData_ptr)
{
LZHAM_ASSERT(m_num_threads);
LZHAM_ASSERT(pFunc);
task tsk;
tsk.m_callback = pFunc;
tsk.m_data = data;
tsk.m_pData_ptr = pData_ptr;
tsk.m_flags = 0;
if (!m_task_stack.try_push(tsk))
return false;
atomic_increment32(&m_num_outstanding_tasks);
m_tasks_available.release(1);
return true;
}
// It's the object's responsibility to delete pObj within the execute_task() method, if needed!
bool task_pool::queue_task(executable_task* pObj, uint64 data, void* pData_ptr)
{
LZHAM_ASSERT(m_num_threads);
LZHAM_ASSERT(pObj);
task tsk;
tsk.m_pObj = pObj;
tsk.m_data = data;
tsk.m_pData_ptr = pData_ptr;
tsk.m_flags = cTaskFlagObject;
if (!m_task_stack.try_push(tsk))
return false;
atomic_increment32(&m_num_outstanding_tasks);
m_tasks_available.release(1);
return true;
}
void task_pool::process_task(task& tsk)
{
if (tsk.m_flags & cTaskFlagObject)
tsk.m_pObj->execute_task(tsk.m_data, tsk.m_pData_ptr);
else
tsk.m_callback(tsk.m_data, tsk.m_pData_ptr);
atomic_decrement32(&m_num_outstanding_tasks);
}
void task_pool::join()
{
task tsk;
while (atomic_add32(&m_num_outstanding_tasks, 0) > 0)
{
if (m_task_stack.pop(tsk))
{
process_task(tsk);
}
else
{
lzham_sleep(1);
}
}
}
void * task_pool::thread_func(void *pContext)
{
task_pool* pPool = static_cast<task_pool*>(pContext);
task tsk;
for ( ; ; )
{
if (!pPool->m_tasks_available.wait())
break;
if (pPool->m_exit_flag)
break;
if (pPool->m_task_stack.pop(tsk))
{
pPool->process_task(tsk);
}
}
return NULL;
}
uint lzham_get_max_helper_threads()
{
#if defined(__GNUC__)
uint num_procs = get_nprocs();
return num_procs ? (num_procs - 1) : 0;
#else
printf("TODO: lzham_get_max_helper_threads(): Implement system specific func to determine the max # of helper threads\n");
// Just assume a dual-core machine.
return 1;
#endif
}
} // namespace lzham
#endif // LZHAM_USE_PTHREADS_API

Some files were not shown because too many files have changed in this diff Show More