фыв
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,139 @@
|
||||
#pragma once
|
||||
// used: [ext] minhook
|
||||
// @credits: https://github.com/TsudaKageyu/minhook
|
||||
#include "../../dependencies/minhook/minhook.h"
|
||||
|
||||
// used: l_print
|
||||
#include "log.h"
|
||||
|
||||
template <typename T>
|
||||
class CBaseHookObject
|
||||
{
|
||||
public:
|
||||
/// setup hook and replace function
|
||||
/// @returns: true if hook has been successfully created, false otherwise
|
||||
bool Create(void* pFunction, void* pDetour)
|
||||
{
|
||||
if (pFunction == nullptr || pDetour == nullptr)
|
||||
return false;
|
||||
|
||||
pBaseFn = pFunction;
|
||||
pReplaceFn = pDetour;
|
||||
|
||||
if (const MH_STATUS status = MH_CreateHook(pBaseFn, pReplaceFn, &pOriginalFn); status != MH_OK)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("failed to create hook, status: \"") << MH_StatusToString(status) << CS_XOR("\" with base address: ") << L::AddFlags(LOG_MODE_INT_SHOWBASE | LOG_MODE_INT_FORMAT_HEX) << reinterpret_cast<std::uintptr_t>(pBaseFn);
|
||||
#else
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("failed to create hook");
|
||||
#endif
|
||||
|
||||
CS_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Replace())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// patch memory to jump to our function instead of original
|
||||
/// @returns: true if hook has been successfully applied, false otherwise
|
||||
bool Replace()
|
||||
{
|
||||
// check is hook has been created
|
||||
if (pBaseFn == nullptr)
|
||||
return false;
|
||||
|
||||
// check that function isn't already hooked
|
||||
if (bIsHooked)
|
||||
return false;
|
||||
|
||||
if (const MH_STATUS status = MH_EnableHook(pBaseFn); status != MH_OK)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("failed to enable hook, status: \"") << MH_StatusToString(status) << CS_XOR("\" with base address: ") << L::AddFlags(LOG_MODE_INT_SHOWBASE | LOG_MODE_INT_FORMAT_HEX) << reinterpret_cast<std::uintptr_t>(pBaseFn);
|
||||
#else
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("failed to enable hook");
|
||||
#endif
|
||||
|
||||
CS_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// switch hook state
|
||||
bIsHooked = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// restore original function call and cleanup hook data
|
||||
/// @returns: true if hook has been successfully removed, false otherwise
|
||||
bool Remove()
|
||||
{
|
||||
// restore it at first
|
||||
if (!Restore())
|
||||
return false;
|
||||
|
||||
if (const MH_STATUS status = MH_RemoveHook(pBaseFn); status != MH_OK)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("failed to remove hook, status: \"") << MH_StatusToString(status) << CS_XOR("\" with base address: ") << L::AddFlags(LOG_MODE_INT_SHOWBASE | LOG_MODE_INT_FORMAT_HEX) << reinterpret_cast<std::uintptr_t>(pBaseFn);
|
||||
#else
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("failed to remove hook");
|
||||
#endif
|
||||
|
||||
CS_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// restore patched memory to original function call
|
||||
/// @returns: true if hook has been successfully restored, false otherwise
|
||||
bool Restore()
|
||||
{
|
||||
// check that function is hooked
|
||||
if (!bIsHooked)
|
||||
return false;
|
||||
|
||||
if (const MH_STATUS status = MH_DisableHook(pBaseFn); status != MH_OK)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("failed to restore hook, status: \"") << MH_StatusToString(status) << CS_XOR("\" with base address: ") << L::AddFlags(LOG_MODE_INT_SHOWBASE | LOG_MODE_INT_FORMAT_HEX) << reinterpret_cast<std::uintptr_t>(pBaseFn);
|
||||
#else
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("failed to restore hook");
|
||||
#endif
|
||||
|
||||
CS_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// switch hook state
|
||||
bIsHooked = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @returns: original, unwrapped function that would be called without the hook
|
||||
CS_INLINE T GetOriginal()
|
||||
{
|
||||
return reinterpret_cast<T>(pOriginalFn);
|
||||
}
|
||||
|
||||
/// @returns: true if hook is applied at the time, false otherwise
|
||||
CS_INLINE bool IsHooked() const
|
||||
{
|
||||
return bIsHooked;
|
||||
}
|
||||
|
||||
private:
|
||||
// current hook state
|
||||
bool bIsHooked = false;
|
||||
// function base handle
|
||||
void* pBaseFn = nullptr;
|
||||
// function that being replace the original call
|
||||
void* pReplaceFn = nullptr;
|
||||
// original function
|
||||
void* pOriginalFn = nullptr;
|
||||
};
|
||||
@@ -0,0 +1,946 @@
|
||||
#include "draw.h"
|
||||
|
||||
// used: cheat variables
|
||||
#include "../core/variables.h"
|
||||
// used: viewmatrix
|
||||
#include "../core/sdk.h"
|
||||
|
||||
// used: m_deg2rad
|
||||
#include "math.h"
|
||||
// used: memoryset
|
||||
#include "crt.h"
|
||||
// used: easing
|
||||
#include "easing.h"
|
||||
// used: ipt
|
||||
#include "inputsystem.h"
|
||||
|
||||
// used: [ext] imgui
|
||||
#include "../../dependencies/imgui/imgui_freetype.h"
|
||||
#include "../../dependencies/imgui/imgui_impl_dx11.h"
|
||||
#include "../../dependencies/imgui/imgui_impl_win32.h"
|
||||
|
||||
// used: [resouces] font awesome
|
||||
#include "../../resources/fa_solid_900.h"
|
||||
#include "../../resources/font_awesome_5.h"
|
||||
#include "../core/ImFont.h"
|
||||
#include "../core/imfonts.h"
|
||||
#include "../core/Bgs.h"
|
||||
#include "../core/Header.h"
|
||||
#include "../core/gui.hpp"
|
||||
#include "../cstrike/font.h"
|
||||
#include "../cstrike/texture.h"
|
||||
#include "../dependencies/imgui/imgui_settings.h"
|
||||
// used: engine/engineclient
|
||||
#include "../sdk/interfaces/iengineclient.h"
|
||||
|
||||
//dx11:
|
||||
#include "../sdk/interfaces/iswapchaindx11.h"
|
||||
|
||||
// used: iinputsystem
|
||||
#include "../core/interfaces.h"
|
||||
#include "../sdk/interfaces/iinputsystem.h"
|
||||
|
||||
// used: bMainWindowOpened
|
||||
#include "../core/menu.h"
|
||||
#include "../core/ui_icons.hpp"
|
||||
|
||||
#pragma region imgui_extended
|
||||
static constexpr const char* arrKeyNames[] = {
|
||||
"",
|
||||
"mouse 1", "mouse 2", "cancel", "mouse 3", "mouse 4", "mouse 5", "",
|
||||
"backspace", "tab", "", "", "clear", "enter", "", "",
|
||||
"shift", "control", "alt", "pause", "caps", "", "", "", "", "", "",
|
||||
"escape", "", "", "", "", "space", "page up", "page down",
|
||||
"end", "home", "left", "up", "right", "down", "", "", "",
|
||||
"print", "insert", "delete", "",
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"", "", "", "", "", "", "",
|
||||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
|
||||
"l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
|
||||
"v", "w", "x", "y", "z", "lwin", "rwin", "", "", "",
|
||||
"num0", "num1", "num2", "num3", "num4", "num5",
|
||||
"num6", "num7", "num8", "num9",
|
||||
"*", "+", "", "-", ".", "/",
|
||||
"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8",
|
||||
"f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16",
|
||||
"f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24",
|
||||
"", "", "", "", "", "", "", "",
|
||||
"num lock", "scroll lock",
|
||||
"", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "",
|
||||
"lshift", "rshift", "lctrl",
|
||||
"rctrl", "lmenu", "rmenu"
|
||||
};
|
||||
|
||||
void ImGui::HelpMarker(const char* szDescription)
|
||||
{
|
||||
TextDisabled(CS_XOR("(?)"));
|
||||
if (IsItemHovered())
|
||||
{
|
||||
BeginTooltip();
|
||||
PushTextWrapPos(450.f);
|
||||
TextUnformatted(szDescription);
|
||||
PopTextWrapPos();
|
||||
EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui::HotKey(const char* szLabel, unsigned int* pValue)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* pWindow = g.CurrentWindow;
|
||||
|
||||
if (pWindow->SkipItems)
|
||||
return false;
|
||||
|
||||
ImGuiIO& io = g.IO;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID nIndex = pWindow->GetID(szLabel);
|
||||
|
||||
const float flWidth = CalcItemWidth();
|
||||
const ImVec2 vecLabelSize = CalcTextSize(szLabel, nullptr, true);
|
||||
float xOffset = 50.f;
|
||||
const ImRect rectFrame(pWindow->DC.CursorPos + ImVec2(vecLabelSize.x > 0.0f ? style.ItemInnerSpacing.x + GetFrameHeight() + xOffset : xOffset, 0.0f), pWindow->DC.CursorPos + ImVec2(flWidth + xOffset, vecLabelSize.x > 0.0f ? vecLabelSize.y + style.FramePadding.y : 0.f));
|
||||
const ImRect rectTotal(rectFrame.Min, rectFrame.Max);
|
||||
|
||||
|
||||
ItemSize(rectTotal, style.FramePadding.y);
|
||||
if (!ItemAdd(rectTotal, nIndex, &rectFrame))
|
||||
return false;
|
||||
|
||||
const bool bHovered = ItemHoverable(rectFrame, nIndex, ImGuiItemFlags_None);
|
||||
if (bHovered)
|
||||
{
|
||||
SetHoveredID(nIndex);
|
||||
g.MouseCursor = ImGuiMouseCursor_TextInput;
|
||||
}
|
||||
|
||||
const bool bClicked = bHovered && io.MouseClicked[0];
|
||||
const bool bDoubleClicked = bHovered && io.MouseDoubleClicked[0];
|
||||
if (bClicked || bDoubleClicked)
|
||||
{
|
||||
if (g.ActiveId != nIndex)
|
||||
{
|
||||
CRT::MemorySet(io.MouseDown, 0, sizeof(io.MouseDown));
|
||||
CRT::MemorySet(io.KeysDown, 0, sizeof(io.KeysDown));
|
||||
*pValue = 0U;
|
||||
}
|
||||
|
||||
SetActiveID(nIndex, pWindow);
|
||||
FocusWindow(pWindow);
|
||||
}
|
||||
|
||||
bool bValueChanged = false;
|
||||
if (unsigned int nKey = *pValue; g.ActiveId == nIndex)
|
||||
{
|
||||
for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++)
|
||||
{
|
||||
if (IsMouseDown(n))
|
||||
{
|
||||
switch (n)
|
||||
{
|
||||
case 0:
|
||||
nKey = VK_LBUTTON;
|
||||
break;
|
||||
case 1:
|
||||
nKey = VK_RBUTTON;
|
||||
break;
|
||||
case 2:
|
||||
nKey = VK_MBUTTON;
|
||||
break;
|
||||
case 3:
|
||||
nKey = VK_XBUTTON1;
|
||||
break;
|
||||
case 4:
|
||||
nKey = VK_XBUTTON2;
|
||||
break;
|
||||
}
|
||||
|
||||
bValueChanged = true;
|
||||
ClearActiveID();
|
||||
}
|
||||
}
|
||||
|
||||
if (!bValueChanged)
|
||||
{
|
||||
for (int n = VK_BACK; n <= VK_RMENU; n++)
|
||||
{
|
||||
if (IsKeyDown((ImGuiKey)n))
|
||||
{
|
||||
nKey = n;
|
||||
bValueChanged = true;
|
||||
ClearActiveID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsKeyPressed(ImGuiKey_Escape))
|
||||
{
|
||||
*pValue = 0U;
|
||||
ClearActiveID();
|
||||
}
|
||||
else
|
||||
*pValue = nKey;
|
||||
}
|
||||
|
||||
char szBuffer[64] = {};
|
||||
char* szBufferEnd = CRT::StringCopy(szBuffer, " ");
|
||||
if (*pValue != 0 && g.ActiveId != nIndex)
|
||||
szBufferEnd = CRT::StringCat(szBufferEnd, arrKeyNames[*pValue]);
|
||||
else if (g.ActiveId == nIndex)
|
||||
szBufferEnd = CRT::StringCat(szBufferEnd, CS_XOR("press"));
|
||||
else
|
||||
szBufferEnd = CRT::StringCat(szBufferEnd, CS_XOR("none"));
|
||||
CRT::StringCat(szBufferEnd, " ");
|
||||
|
||||
PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(style.FramePadding.x, -1));
|
||||
|
||||
const ImVec2 vecBufferSize = CalcTextSize(szBuffer);
|
||||
RenderFrame(ImVec2(rectFrame.Max.x - vecBufferSize.x, rectTotal.Min.y), ImVec2(rectFrame.Max.x, rectTotal.Min.y + style.FramePadding.y + vecBufferSize.y), GetColorU32((bHovered || bClicked || bDoubleClicked) ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||
pWindow->DrawList->AddText(ImVec2(rectFrame.Max.x - vecBufferSize.x, rectTotal.Min.y + style.FramePadding.y), GetColorU32(g.ActiveId == nIndex ? ImGuiCol_Text : ImGuiCol_TextDisabled), szBuffer);
|
||||
|
||||
//if (vecLabelSize.x > 0.f)
|
||||
//RenderText(ImVec2(rectTotal.Min.x, rectTotal.Min.y + style.FramePadding.y), szLabel);
|
||||
|
||||
PopStyleVar();
|
||||
return bValueChanged;
|
||||
}
|
||||
|
||||
bool ImGui::HotKey(const char* szLabel, KeyBind_t* pKeyBind, const bool bAllowSwitch)
|
||||
{
|
||||
const bool bValueChanged = HotKey(szLabel, &pKeyBind->uKey);
|
||||
|
||||
if (bAllowSwitch)
|
||||
{
|
||||
|
||||
char* szUniqueID = static_cast<char*>(MEM_STACKALLOC(CRT::StringLength(szLabel) + 6));
|
||||
CRT::StringCat(CRT::StringCopy(szUniqueID, CS_XOR("key##")), szLabel);
|
||||
|
||||
if (IsItemClicked(ImGuiMouseButton_Right))
|
||||
OpenPopup(szUniqueID);
|
||||
|
||||
if (BeginPopup(szUniqueID))
|
||||
{
|
||||
SetNextItemWidth(ImGui::GetWindowWidth() + 20.f);
|
||||
if (Combo(CS_XOR("##keybind.mode"), reinterpret_cast<int*>(&pKeyBind->nMode), CS_XOR("Hold\0Toggle\0\0")))
|
||||
CloseCurrentPopup();
|
||||
|
||||
EndPopup();
|
||||
}
|
||||
|
||||
MEM_STACKFREE(szUniqueID);
|
||||
}
|
||||
|
||||
return bValueChanged;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ImGui::BeginListBox(const char* szLabel, int nItemsCount, int nHeightInItems)
|
||||
{
|
||||
float height = GetTextLineHeightWithSpacing() * ((nHeightInItems < 0 ? ImMin(nItemsCount, 7) : nHeightInItems) + 0.25f) + GetStyle().FramePadding.y * 2.0f;
|
||||
return BeginListBox(szLabel, ImVec2(0.0f, height));
|
||||
}
|
||||
|
||||
bool ImGui::ColorEdit3(const char* szLabel, Color_t* pColor, ImGuiColorEditFlags flags)
|
||||
{
|
||||
return ColorEdit4(szLabel, pColor, flags | ImGuiColorEditFlags_NoAlpha);
|
||||
}
|
||||
|
||||
bool ImGui::ColorEdit4(const char* szLabel, Color_t* pColor, ImGuiColorEditFlags flags, int type)
|
||||
{
|
||||
if (type == 0) {
|
||||
ImVec2 v1 = ImGui::GetItemRectSize();
|
||||
ImVec2 v1pos = ImGui::GetCursorPos();
|
||||
ImGui::SameLine(v1pos.x + v1.x + 230);
|
||||
}
|
||||
if (type == 1) {
|
||||
ImVec2 v1 = ImGui::GetItemRectSize();
|
||||
ImVec2 v1pos = ImGui::GetCursorPos();
|
||||
ImGui::SameLine(v1pos.x + v1.x + 75.f);
|
||||
}
|
||||
float arrColor[4];
|
||||
pColor->BaseAlpha(arrColor);
|
||||
|
||||
if (ColorEdit4(szLabel, &arrColor[0], flags))
|
||||
{
|
||||
*pColor = Color_t::FromBase4(arrColor);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool ImGui::ColorEdit3(const char* szLabel, ColorPickerVar_t* pColor, ImGuiColorEditFlags flags)
|
||||
{
|
||||
return ColorEdit4(szLabel, pColor, flags | ImGuiColorEditFlags_NoAlpha);
|
||||
}
|
||||
|
||||
bool ImGui::ColorEdit4(const char* szLabel, ColorPickerVar_t* pColorVar, ImGuiColorEditFlags flags, int type)
|
||||
{
|
||||
const bool bResult = ColorEdit4(szLabel, &pColorVar->colValue, flags);
|
||||
|
||||
// switch rainbow mode on middle mouse click
|
||||
if (IsItemHovered())
|
||||
{
|
||||
// tooltip for turn on/off rainbow mode
|
||||
BeginTooltip();
|
||||
{
|
||||
PushTextWrapPos(450.f);
|
||||
TextUnformatted(CS_XOR("use mouse middle-click to turn on/off rainbow mode!"));
|
||||
PopTextWrapPos();
|
||||
}
|
||||
EndTooltip();
|
||||
|
||||
if (IsMouseClicked(ImGuiMouseButton_Middle))
|
||||
pColorVar->bRainbow = !pColorVar->bRainbow;
|
||||
}
|
||||
|
||||
// open the context popup
|
||||
OpenPopupOnItemClick(CS_XOR("context##color.picker"), ImGuiPopupFlags_MouseButtonRight);
|
||||
// @todo: cleaner code
|
||||
SetNextWindowSize(ImVec2((pColorVar->bRainbow ? 120.f : 60.f) * D::CalculateDPI(C_GET(int, Vars.nDpiScale)), 0.f));
|
||||
if (BeginPopup(CS_XOR("context##color.picker")))
|
||||
{
|
||||
if (Button(CS_XOR("copy##color.picker"), ImVec2(-1, 25 * D::CalculateDPI(C_GET(int, Vars.nDpiScale)))))
|
||||
{
|
||||
// @todo: im32 hex format is AARRGGBB, but we need RRGGBBAA
|
||||
CRT::String_t<64U> szBuffer(CS_XOR("#%X"), pColorVar->colValue.GetU32());
|
||||
SetClipboardText(szBuffer.Data());
|
||||
szBuffer.Clear();
|
||||
|
||||
CloseCurrentPopup();
|
||||
}
|
||||
|
||||
if (Button(CS_XOR("paste##color.picker"), ImVec2(-1, 25 * D::CalculateDPI(C_GET(int, Vars.nDpiScale)))))
|
||||
{
|
||||
const char* szClipboardText = GetClipboardText();
|
||||
// @note: +1U for '#' prefix skipping
|
||||
const ImU32 uConvertedColor = CRT::StringToInteger<ImU32>(szClipboardText + 1U, nullptr, 16);
|
||||
|
||||
pColorVar->colValue = Color_t(uConvertedColor);
|
||||
CloseCurrentPopup();
|
||||
}
|
||||
|
||||
if (pColorVar->bRainbow)
|
||||
{
|
||||
// @note: urgh padding moment idk
|
||||
SetNextItemWidth(ImGui::GetWindowWidth() * 0.90f + 1.f);
|
||||
SliderFloat(CS_XOR("##speed.color.picker"), &pColorVar->flRainbowSpeed, 0.f, 5.f, CS_XOR("speed: %.1f"), ImGuiSliderFlags_AlwaysClamp);
|
||||
}
|
||||
|
||||
EndPopup();
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
#include <d3dcompiler.h>
|
||||
|
||||
// Forward declaration of the ImGui render function.
|
||||
void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data);
|
||||
void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* ctx);
|
||||
|
||||
// thread-safe draw data mutex
|
||||
static SRWLOCK drawLock = {};
|
||||
|
||||
static void* __cdecl ImGuiAllocWrapper(const std::size_t nSize, [[maybe_unused]] void* pUserData = nullptr)
|
||||
{
|
||||
return MEM::HeapAlloc(nSize);
|
||||
}
|
||||
|
||||
static void __cdecl ImGuiFreeWrapper(void* pMemory, [[maybe_unused]] void* pUserData = nullptr) noexcept
|
||||
{
|
||||
MEM::HeapFree(pMemory);
|
||||
}
|
||||
|
||||
// Function to load a texture from memory
|
||||
HRESULT LoadTextureFromMemory(ID3D11Device* device, const void* data, size_t dataSize, ID3D11ShaderResourceView** textureView)
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Width = 512; // Set the width of your texture
|
||||
desc.Height = 512; // Set the height of your texture
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // Adjust the format based on your texture data
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA initData;
|
||||
ZeroMemory(&initData, sizeof(initData));
|
||||
initData.pSysMem = data;
|
||||
initData.SysMemPitch = static_cast<UINT>(desc.Width * 4); // Assuming 4 bytes per pixel, adjust as needed
|
||||
|
||||
ID3D11Texture2D* texture = nullptr;
|
||||
HRESULT hr = device->CreateTexture2D(&desc, &initData, &texture);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
||||
srvDesc.Format = desc.Format;
|
||||
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
|
||||
hr = device->CreateShaderResourceView(texture, &srvDesc, textureView);
|
||||
|
||||
// Release the texture because we have created a shader resource view
|
||||
texture->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
#include "../core/hooks.h"
|
||||
|
||||
// Simple helper function to load an image into a DX11 texture with common settings
|
||||
bool LoadTextureFromFile(const char* filename, ID3D11ShaderResourceView** out_srv, int* out_width, int* out_height)
|
||||
{
|
||||
// Load from disk into a raw RGBA buffer
|
||||
int image_width = 0;
|
||||
int image_height = 0;
|
||||
unsigned char* image_data = stbi_load(filename, &image_width, &image_height, NULL, 4);
|
||||
if (image_data == NULL)
|
||||
return false;
|
||||
|
||||
// Create texture
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Width = image_width;
|
||||
desc.Height = image_height;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
ID3D11Texture2D* pTexture = NULL;
|
||||
D3D11_SUBRESOURCE_DATA subResource;
|
||||
subResource.pSysMem = image_data;
|
||||
subResource.SysMemPitch = desc.Width * 4;
|
||||
subResource.SysMemSlicePitch = 0;
|
||||
I::Device->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
|
||||
// Create texture view
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
||||
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
I::Device->CreateShaderResourceView(pTexture, &srvDesc, out_srv);
|
||||
pTexture->Release();
|
||||
|
||||
*out_width = image_width;
|
||||
*out_height = image_height;
|
||||
stbi_image_free(image_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
#include "../icons/iconscs2.c"
|
||||
int my_image_width = 170;
|
||||
int my_image_height = 295;
|
||||
float font_size = 18.f; // The desired font size
|
||||
|
||||
bool D::InitImGui()
|
||||
{
|
||||
if (bInitialized) {
|
||||
L_PRINT(LOG_WARNING) << CS_XOR("Aready Initialized overlay");
|
||||
return false;
|
||||
}
|
||||
ImGui::SetAllocatorFunctions(ImGuiAllocWrapper, ImGuiFreeWrapper);
|
||||
|
||||
ImGui::CreateContext();
|
||||
ImGui::SetCurrentContext(ImGui::GetCurrentContext());
|
||||
ImGui_ImplWin32_Init(IPT::hWindow);
|
||||
ImGui_ImplDX11_Init(I::Device, I::DeviceContext);
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
io.IniFilename = nullptr;
|
||||
io.LogFilename = nullptr;
|
||||
|
||||
io.MouseDrawCursor = MENU::bMainWindowOpened;
|
||||
|
||||
|
||||
// create draw data containers
|
||||
pDrawListActive = IM_NEW(ImDrawList)(ImGui::GetDrawListSharedData());
|
||||
pDrawListSafe = IM_NEW(ImDrawList)(ImGui::GetDrawListSharedData());
|
||||
pDrawListRender = IM_NEW(ImDrawList)(ImGui::GetDrawListSharedData());
|
||||
|
||||
#pragma region draw_setup_style
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.Alpha = 1.0f;
|
||||
style.WindowPadding = ImVec2(8, 8);
|
||||
style.WindowRounding = 4.0f;
|
||||
style.WindowBorderSize = 1.0f;
|
||||
style.WindowMinSize = ImVec2(32, 32);
|
||||
style.WindowTitleAlign = ImVec2(0.5f, 0.5f);
|
||||
style.ChildRounding = 4.0f;
|
||||
style.ChildBorderSize = 1.0f;
|
||||
style.PopupRounding = 4.0f;
|
||||
style.PopupBorderSize = 1.0f;
|
||||
style.FramePadding = ImVec2(4, 2);
|
||||
style.FrameRounding = 4.0f;
|
||||
style.FrameBorderSize = 1.0f;
|
||||
style.ItemSpacing = ImVec2(8, 4);
|
||||
style.ItemInnerSpacing = ImVec2(4, 4);
|
||||
style.IndentSpacing = 6.0f;
|
||||
style.ColumnsMinSpacing = 6.0f;
|
||||
style.ScrollbarSize = 6.0f;
|
||||
style.ScrollbarRounding = 9.0f;
|
||||
style.GrabMinSize = 0.0f;
|
||||
style.GrabRounding = 4.0f;
|
||||
style.TabRounding = 4.0f;
|
||||
style.TabBorderSize = 1.0f;
|
||||
style.ButtonTextAlign = ImVec2(0.5f, 0.5f);
|
||||
style.SelectableTextAlign = ImVec2(0.0f, 0.5f);
|
||||
style.WindowShadowSize = 0.f;
|
||||
style.AntiAliasedLines = true;
|
||||
style.AntiAliasedFill = true;
|
||||
style.AntiAliasedLinesUseTex = true;
|
||||
style.ColorButtonPosition = ImGuiDir_Right;
|
||||
style.Colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
|
||||
style.Colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);
|
||||
style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
style.Colors[ImGuiCol_Header] = ImVec4{ ImColor(15, 18, 15, 155) };
|
||||
style.Colors[ImGuiCol_HeaderHovered] = ImVec4{ ImColor(15, 18, 15, 155) };
|
||||
style.Colors[ImGuiCol_HeaderActive] = ImVec4{ ImColor(15, 18, 15, 155) };
|
||||
style.Colors[ImGuiCol_Separator] = style.Colors[ImGuiCol_Border];
|
||||
style.Colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f);
|
||||
style.Colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 0.00f);
|
||||
style.Colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0);
|
||||
style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0);
|
||||
style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0);
|
||||
style.Colors[ImGuiCol_Button] = ImVec4{ ImColor(15, 18, 15, 155) };
|
||||
style.Colors[ImGuiCol_ButtonHovered] = ImVec4{ ImColor(15, 18, 15, 155) };
|
||||
style.Colors[ImGuiCol_ButtonActive] = ImVec4{ ImColor(15, 18, 15, 155) };
|
||||
#pragma endregion
|
||||
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
|
||||
|
||||
for (int i = 0; i < CS_ARRAYSIZE(FONT::pMenu); i++) {
|
||||
const float flFontSize = 16.f * CalculateDPI(i);
|
||||
FONT::pMenu[i] = io.Fonts->AddFontFromFileTTF(CS_XOR("C:\\Windows\\Fonts\\Verdana.ttf"), flFontSize, nullptr, io.Fonts->GetGlyphRangesCyrillic());
|
||||
}
|
||||
|
||||
ImFontConfig verdana_cfg;
|
||||
ImFontConfig name_cfg;
|
||||
ImFontConfig seg_cfg;
|
||||
ImFontConfig tahoma_cfg;
|
||||
verdana_cfg.FontBuilderFlags = ImGuiFreeTypeBuilderFlags_LightHinting;
|
||||
tahoma_cfg.FontBuilderFlags = ImGuiFreeTypeBuilderFlags_Bitmap;
|
||||
seg_cfg.FontBuilderFlags = ImGuiFreeTypeBuilderFlags_Monochrome | ImGuiFreeTypeBuilderFlags_NoHinting;
|
||||
name_cfg.FontBuilderFlags = ImGuiFreeTypeBuilderFlags_ForceAutoHint;
|
||||
|
||||
ImFontConfig cfg;
|
||||
cfg.FontBuilderFlags = ImGuiFreeTypeBuilderFlags_ForceAutoHint | ImGuiFreeTypeBuilderFlags_LightHinting | ImGuiFreeTypeBuilderFlags_LoadColor;
|
||||
|
||||
font::lexend_general_bold = io.Fonts->AddFontFromFileTTF(("C:\\Windows\\Fonts\\segoeui.ttf"), 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
font::lexend_bold = io.Fonts->AddFontFromFileTTF(("C:\\Windows\\Fonts\\segoeui.ttf"), 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
|
||||
font::lexend_regular = io.Fonts->AddFontFromMemoryTTF(lexend_regular, sizeof(lexend_regular), 14.f, &cfg, io.Fonts->GetGlyphRangesCyrillic());
|
||||
font::icomoon = io.Fonts->AddFontFromMemoryTTF(icomoon, sizeof(icomoon), 20.f, &cfg, io.Fonts->GetGlyphRangesCyrillic());
|
||||
|
||||
font::icomoon_widget = io.Fonts->AddFontFromMemoryTTF(icomoon_widget, sizeof(icomoon_widget), 15.f, &cfg, io.Fonts->GetGlyphRangesCyrillic());
|
||||
font::icomoon_widget2 = io.Fonts->AddFontFromMemoryTTF(icomoon, sizeof(icomoon), 16.f, &cfg, io.Fonts->GetGlyphRangesCyrillic());
|
||||
|
||||
|
||||
FONT::pExtra = io.Fonts->AddFontFromFileTTF(CS_XOR("C:\\Windows\\Fonts\\Verdana.ttf"), 12.f, &verdana_cfg, io.Fonts->GetGlyphRangesCyrillic());
|
||||
FONT::pEspHealth = io.Fonts->AddFontFromFileTTF(CS_XOR("C:\\Windows\\Fonts\\Verdana.ttf"), 9.f, &verdana_cfg, io.Fonts->GetGlyphRangesCyrillic());
|
||||
FONT::pMenuTabsDesc = io.Fonts->AddFontFromFileTTF(CS_XOR("C:\\Windows\\Fonts\\Verdana.ttf"), 12.f, &verdana_cfg, io.Fonts->GetGlyphRangesCyrillic());
|
||||
FONT::pEspWepName = io.Fonts->AddFontFromFileTTF(CS_XOR("C:\\Windows\\Fonts\\Verdana.ttf"), 10.f, &name_cfg, io.Fonts->GetGlyphRangesDefault());
|
||||
FONT::pEspName = io.Fonts->AddFontFromFileTTF(CS_XOR("C:\\Windows\\Fonts\\Verdana.ttf"), 11.5f, &name_cfg, io.Fonts->GetGlyphRangesDefault());
|
||||
FONT::pVisual = io.Fonts->AddFontFromFileTTF(CS_XOR("C:\\Windows\\Fonts\\Tahoma.ttf"), 14.f, &tahoma_cfg, io.Fonts->GetGlyphRangesCyrillic());
|
||||
FONT::pEspFlagsName = io.Fonts->AddFontFromFileTTF(CS_XOR("C:\\Windows\\Fonts\\Verdana.ttf"), 11.f, &verdana_cfg, io.Fonts->GetGlyphRangesDefault());
|
||||
FONT::pEspIcons = io.Fonts->AddFontFromFileTTF(CS_XOR("C:\\Windows\\Fonts\\Verdana.ttf"), 10.f, &name_cfg, io.Fonts->GetGlyphRangesDefault());
|
||||
|
||||
LoadTextureFromFile("C:\\Program Files\\cs2.png", &I::Maintexture, &my_image_width, &my_image_height);
|
||||
|
||||
FONT::isis = io.Fonts->AddFontFromFileTTF(("C:\\Windows\\Fonts\\segoeui.ttf"), 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
FONT::icon_font = io.Fonts->AddFontFromFileTTF(CS_XOR("C:\\Windows\\Fonts\\Tahoma.ttf"), 18.f, &tahoma_cfg, io.Fonts->GetGlyphRangesCyrillic());
|
||||
FONT::font = io.Fonts->AddFontFromFileTTF(("C:\\Windows\\Fonts\\segoeui.ttf"), 16.0f, NULL, io.Fonts->GetGlyphRangesCyrillic());
|
||||
FONT::mainfont = io.Fonts->AddFontFromFileTTF(("C:\\Windows\\Fonts\\segoeui.ttf"), 18.f, NULL, io.Fonts->GetGlyphRangesCyrillic());
|
||||
|
||||
io.Fonts->FontBuilderFlags = ImGuiFreeTypeBuilderFlags_LightHinting;
|
||||
bInitialized = io.Fonts->Build();
|
||||
return bInitialized;
|
||||
}
|
||||
|
||||
#include "../cstrike/features/visuals/overlay.h"
|
||||
|
||||
void D::Destroy()
|
||||
{
|
||||
// check is it already destroyed or wasn't initialized at all
|
||||
if (!bInitialized)
|
||||
return;
|
||||
|
||||
ImGui::GetIO().Fonts->Clear();
|
||||
ImGui::GetIO().Fonts->TexID = 0;
|
||||
|
||||
// free draw data containers
|
||||
IM_DELETE(pDrawListActive);
|
||||
IM_DELETE(pDrawListSafe);
|
||||
IM_DELETE(pDrawListRender);
|
||||
|
||||
// shutdown imgui direct<x9 renderer binding
|
||||
ImGui_ImplDX11_Shutdown();
|
||||
|
||||
// shutdown imgui win32 platform binding
|
||||
ImGui_ImplWin32_Shutdown();
|
||||
|
||||
// destroy imgui context
|
||||
ImGui::DestroyContext();
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("\"Destroy\" unloaded");
|
||||
|
||||
bInitialized = false;
|
||||
}
|
||||
#pragma region draw_render
|
||||
void D::Render() {
|
||||
ImGui_ImplDX11_NewFrame();
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
|
||||
|
||||
F::VISUALS::OVERLAY::Render();
|
||||
|
||||
MENU::RenderMainWindow();
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
I::DeviceContext->OMSetRenderTargets(1, &I::RenderTargetView, NULL);
|
||||
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region draw_callbacks
|
||||
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
bool D::OnWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
// check is drawing initialized
|
||||
if (!bInitialized)
|
||||
return false;
|
||||
|
||||
IPT::OnWndProc(hWnd, uMsg, wParam, lParam);
|
||||
|
||||
// switch menu state
|
||||
if (IPT::IsKeyReleased(C_GET(unsigned int, Vars.nMenuKey)))
|
||||
{
|
||||
MENU::bMainWindowOpened = !MENU::bMainWindowOpened;
|
||||
// update animation
|
||||
MENU::animMenuDimBackground.Switch();
|
||||
// handle mouse input when menu is opened
|
||||
if (I::InputSystem->IsRelativeMouseMode())
|
||||
{
|
||||
// set input system mouse mode
|
||||
MEM::fnSetRelativeMouseMode(!MENU::bMainWindowOpened);
|
||||
// set input system window grab state
|
||||
MEM::fnSetWindowGrab(I::InputSystem->GetSDLWindow(), !MENU::bMainWindowOpened);
|
||||
// warp our cursor into middle of the screen
|
||||
const ImVec2 vecScreenCenter = ImGui::GetIO().DisplaySize / 2.f;
|
||||
MEM::fnWarpMouseInWindow(nullptr, vecScreenCenter.x, vecScreenCenter.y);
|
||||
}
|
||||
}
|
||||
|
||||
// handle ImGui's window messages and block game's input if menu is opened
|
||||
return ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam) || MENU::bMainWindowOpened;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region draw_main
|
||||
|
||||
void D::RenderDrawData(ImDrawData* pDrawData)
|
||||
{
|
||||
if (!pDrawData)
|
||||
return;
|
||||
|
||||
if (TryAcquireSRWLockExclusive(&drawLock))
|
||||
{
|
||||
*pDrawListRender = *pDrawListSafe;
|
||||
ReleaseSRWLockExclusive(&drawLock);
|
||||
}
|
||||
|
||||
if (pDrawListRender->CmdBuffer.empty())
|
||||
return;
|
||||
|
||||
// remove trailing command if unused
|
||||
// @note: equivalent to pDrawList->_PopUnusedDrawCmd()
|
||||
const ImDrawCmd& lastCommand = pDrawListRender->CmdBuffer.back();
|
||||
if ( lastCommand.ElemCount == 0 && lastCommand.UserCallback == nullptr)
|
||||
{
|
||||
pDrawListRender->CmdBuffer.pop_back();
|
||||
if (pDrawListRender->CmdBuffer.empty())
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiContext* pContext = ImGui::GetCurrentContext();
|
||||
ImGuiViewportP* pViewport = pContext->Viewports[0];
|
||||
ImVector<ImDrawList*>* vecDrawLists = pViewport->DrawDataBuilder.Layers[0];
|
||||
vecDrawLists->push_front(pDrawListRender); // this one being most background
|
||||
|
||||
pDrawData->CmdLists.push_front(pDrawListRender);
|
||||
pDrawData->CmdListsCount = vecDrawLists->Size;
|
||||
pDrawData->TotalVtxCount += pDrawListRender->VtxBuffer.Size;
|
||||
pDrawData->TotalIdxCount += pDrawListRender->IdxBuffer.Size;
|
||||
}
|
||||
|
||||
void D::ResetDrawData()
|
||||
{
|
||||
pDrawListActive->_ResetForNewFrame();
|
||||
pDrawListActive->PushTextureID(ImGui::GetIO().Fonts->TexID);
|
||||
pDrawListActive->PushClipRectFullScreen();
|
||||
}
|
||||
|
||||
void D::SwapDrawData()
|
||||
{
|
||||
::AcquireSRWLockExclusive(&drawLock);
|
||||
|
||||
|
||||
*pDrawListSafe = *pDrawListActive;
|
||||
|
||||
::ReleaseSRWLockExclusive(&drawLock);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region draw_bindings
|
||||
|
||||
bool D::WorldToScreen(const Vector_t& in, ImVec2& out)
|
||||
{
|
||||
if (!ImGui::GetCurrentContext())
|
||||
return false;
|
||||
|
||||
auto z = SDK::ViewMatrix[3][0] * in.x + SDK::ViewMatrix[3][1] * in.y + SDK::ViewMatrix[3][2] * in.z + SDK::ViewMatrix[3][3];
|
||||
if (z < 0.001f) return false;
|
||||
|
||||
out = ImGui::GetIO().DisplaySize * 0.5f;
|
||||
out.x *= 1.0f + (SDK::ViewMatrix[0][0] * in.x + SDK::ViewMatrix[0][1] * in.y + SDK::ViewMatrix[0][2] * in.z + SDK::ViewMatrix[0][3]) / z;
|
||||
out.y *= 1.0f - (SDK::ViewMatrix[1][0] * in.x + SDK::ViewMatrix[1][1] * in.y + SDK::ViewMatrix[1][2] * in.z + SDK::ViewMatrix[1][3]) / z;
|
||||
|
||||
// Prevents rounded corners.
|
||||
out = ImFloor(out);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float D::CalculateDPI(const int nScaleTarget)
|
||||
{
|
||||
switch ((EMiscDpiScale)nScaleTarget)
|
||||
{
|
||||
case EMiscDpiScale::MISC_DPISCALE_DEFAULT:
|
||||
return 1.f;
|
||||
case EMiscDpiScale::MISC_DPISCALE_125:
|
||||
return 1.25f;
|
||||
case EMiscDpiScale::MISC_DPISCALE_150:
|
||||
return 1.5f;
|
||||
case EMiscDpiScale::MISC_DPISCALE_175:
|
||||
return 1.75f;
|
||||
case EMiscDpiScale::MISC_DPISCALE_200:
|
||||
return 2.f;
|
||||
default:
|
||||
return 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
void D::AddDrawListRect(ImDrawList* pDrawList, const ImVec2& vecMin, const ImVec2& vecMax, const Color_t& colRect, const unsigned int uFlags, const Color_t& colOutline, const float flRounding, const ImDrawFlags roundingCorners, float flThickness, const float flOutlineThickness)
|
||||
{
|
||||
if (pDrawList == nullptr)
|
||||
pDrawList = pDrawListActive;
|
||||
|
||||
const ImU32 colRectPacked = colRect.GetU32();
|
||||
const ImU32 colOutlinePacked = colOutline.GetU32();
|
||||
|
||||
if (uFlags & DRAW_RECT_FILLED)
|
||||
pDrawList->AddRectFilled(vecMin, vecMax, colRectPacked, flRounding, roundingCorners);
|
||||
else
|
||||
{
|
||||
pDrawList->AddRect(vecMin, vecMax, colRectPacked, flRounding, roundingCorners, flThickness);
|
||||
flThickness *= 0.5f;
|
||||
}
|
||||
|
||||
const float flHalfOutlineThickness = flOutlineThickness * 0.5f;
|
||||
const ImVec2 vecThicknessOffset = { flThickness + flHalfOutlineThickness, flThickness + flHalfOutlineThickness };
|
||||
|
||||
if (uFlags & DRAW_RECT_BORDER)
|
||||
pDrawList->AddRect(vecMin + vecThicknessOffset, vecMax - vecThicknessOffset, colOutlinePacked, flRounding, roundingCorners, flOutlineThickness);
|
||||
|
||||
if (uFlags & DRAW_RECT_OUTLINE)
|
||||
pDrawList->AddRect(vecMin - vecThicknessOffset, vecMax + vecThicknessOffset, colOutlinePacked, flRounding, roundingCorners, flOutlineThickness);
|
||||
}
|
||||
|
||||
void D::AddDrawListRectMultiColor(ImDrawList* pDrawList, const ImVec2& vecMin, const ImVec2& vecMax, const Color_t& colUpperLeft, const Color_t& colUpperRight, const Color_t& colBottomRight, const Color_t& colBottomLeft)
|
||||
{
|
||||
if (pDrawList == nullptr)
|
||||
pDrawList = pDrawListActive;
|
||||
|
||||
pDrawList->AddRectFilledMultiColor(vecMin, vecMax, colUpperLeft.GetU32(), colUpperRight.GetU32(), colBottomRight.GetU32(), colBottomLeft.GetU32());
|
||||
}
|
||||
|
||||
void D::AddDrawListCircle(ImDrawList* pDrawList, const ImVec2& vecCenter, const float flRadius, const Color_t& colCircle, const int nSegments, const unsigned int uFlags, const Color_t& colOutline, float flThickness, const float flOutlineThickness)
|
||||
{
|
||||
if (pDrawList == nullptr)
|
||||
pDrawList = pDrawListActive;
|
||||
|
||||
const ImU32 colCirclePacked = colCircle.GetU32();
|
||||
|
||||
if (uFlags & DRAW_CIRCLE_FILLED)
|
||||
{
|
||||
pDrawList->AddCircleFilled(vecCenter, flRadius, colCirclePacked, nSegments);
|
||||
flThickness = 0.0f;
|
||||
}
|
||||
else
|
||||
pDrawList->AddCircle(vecCenter, flRadius, colCirclePacked, nSegments, flThickness);
|
||||
|
||||
if (uFlags & DRAW_CIRCLE_OUTLINE)
|
||||
pDrawList->AddCircle(vecCenter, flRadius + flOutlineThickness, colOutline.GetU32(), nSegments, flThickness + flOutlineThickness);
|
||||
}
|
||||
|
||||
void D::AddDrawListArc(ImDrawList* pDrawList, const ImVec2& vecPosition, const float flRadius, const float flMinimumAngle, const float flMaximumAngle, const Color_t& colArc, const float flThickness)
|
||||
{
|
||||
if (pDrawList == nullptr)
|
||||
pDrawList = pDrawListActive;
|
||||
|
||||
pDrawList->PathArcTo(vecPosition, flRadius, M_DEG2RAD(flMinimumAngle), M_DEG2RAD(flMaximumAngle), 32);
|
||||
pDrawList->PathStroke(colArc.GetU32(), false, flThickness);
|
||||
}
|
||||
|
||||
void D::AddDrawListLine(ImDrawList* pDrawList, const ImVec2& vecFirst, const ImVec2& vecSecond, const Color_t& colLine, const float flThickness)
|
||||
{
|
||||
if (pDrawList == nullptr)
|
||||
pDrawList = pDrawListActive;
|
||||
|
||||
pDrawList->AddLine(vecFirst, vecSecond, colLine.GetU32(), flThickness);
|
||||
}
|
||||
|
||||
void D::AddDrawListTriangle(ImDrawList* pDrawList, const ImVec2& vecFirst, const ImVec2& vecSecond, const ImVec2& vecThird, const Color_t& colTriangle, const unsigned int uFlags, const Color_t& colOutline, const float flThickness)
|
||||
{
|
||||
if (pDrawList == nullptr)
|
||||
pDrawList = pDrawListActive;
|
||||
|
||||
const ImU32 colTrianglePacked = colTriangle.GetU32();
|
||||
|
||||
if (uFlags & DRAW_TRIANGLE_FILLED)
|
||||
pDrawList->AddTriangleFilled(vecFirst, vecSecond, vecThird, colTrianglePacked);
|
||||
else
|
||||
pDrawList->AddTriangle(vecFirst, vecSecond, vecThird, colTrianglePacked, flThickness);
|
||||
|
||||
if (uFlags & DRAW_TRIANGLE_OUTLINE)
|
||||
pDrawList->AddTriangle(vecFirst, vecSecond, vecThird, colOutline.GetU32(), flThickness + 1.0f);
|
||||
}
|
||||
|
||||
void D::AddDrawListQuad(ImDrawList* pDrawList, const ImVec2& vecFirst, const ImVec2& vecSecond, const ImVec2& vecThird, const ImVec2& vecFourth, const Color_t& colQuad, const unsigned int uFlags, const Color_t& colOutline, const float flThickness)
|
||||
{
|
||||
if (pDrawList == nullptr)
|
||||
pDrawList = pDrawListActive;
|
||||
|
||||
const ImU32 colQuadPacked = colQuad.GetU32();
|
||||
|
||||
if (uFlags & DRAW_QUAD_FILLED)
|
||||
pDrawList->AddQuadFilled(vecFirst, vecSecond, vecThird, vecFourth, colQuadPacked);
|
||||
else
|
||||
pDrawList->AddQuad(vecFirst, vecSecond, vecThird, vecFourth, colQuadPacked, flThickness);
|
||||
|
||||
if (uFlags & DRAW_QUAD_OUTLINE)
|
||||
pDrawList->AddQuad(vecFirst, vecSecond, vecThird, vecFourth, colOutline.GetU32(), flThickness + 1.0f);
|
||||
}
|
||||
|
||||
void D::AddDrawListPolygon(ImDrawList* pDrawList, const ImVec2* vecPoints, const int nPointsCount, const Color_t& colPolygon, unsigned int uFlags, const Color_t& colOutline, const bool bClosed, const float flThickness)
|
||||
{
|
||||
if (pDrawList == nullptr)
|
||||
pDrawList = pDrawListActive;
|
||||
|
||||
const ImU32 colPolygonPacked = colPolygon.GetU32();
|
||||
|
||||
if (uFlags & DRAW_POLYGON_FILLED)
|
||||
pDrawList->AddConvexPolyFilled(vecPoints, nPointsCount, colPolygonPacked);
|
||||
else
|
||||
pDrawList->AddPolyline(vecPoints, nPointsCount, colPolygonPacked, bClosed, flThickness);
|
||||
|
||||
if (uFlags & DRAW_POLYGON_OUTLINE)
|
||||
pDrawList->AddPolyline(vecPoints, nPointsCount, colOutline.GetU32(), bClosed, flThickness + 1.0f);
|
||||
}
|
||||
|
||||
void D::AddDrawListText(ImDrawList* pDrawList, const ImFont* pFont, const ImVec2& vecPosition, const char* szText, const Color_t& colText, const unsigned int uFlags, const Color_t& colOutline, const float flThickness)
|
||||
{
|
||||
if (pDrawList == nullptr)
|
||||
pDrawList = pDrawListActive;
|
||||
|
||||
// set font texture
|
||||
pDrawList->PushTextureID(pFont->ContainerAtlas->TexID);
|
||||
|
||||
const ImU32 colOutlinePacked = colOutline.GetU32();
|
||||
|
||||
if (uFlags & DRAW_TEXT_DROPSHADOW)
|
||||
pDrawList->AddText(pFont, pFont->FontSize, vecPosition + ImVec2(flThickness, flThickness), colOutlinePacked, szText);
|
||||
else if (uFlags & DRAW_TEXT_OUTLINE)
|
||||
{
|
||||
pDrawList->AddText(pFont, pFont->FontSize, vecPosition + ImVec2(flThickness, -flThickness), colOutlinePacked, szText);
|
||||
pDrawList->AddText(pFont, pFont->FontSize, vecPosition + ImVec2(-flThickness, flThickness), colOutlinePacked, szText);
|
||||
}
|
||||
|
||||
pDrawList->AddText(pFont, pFont->FontSize, vecPosition, colText.GetU32(), szText);
|
||||
pDrawList->PopTextureID();
|
||||
}
|
||||
|
||||
void D::AddDrawListShadowRect(ImDrawList* pDrawList, const ImVec2& vecMin, const ImVec2& vecMax, const Color_t& colShadow, float flThickness, float flRounding, ImDrawFlags roundingCorners)
|
||||
{
|
||||
if (pDrawList == nullptr)
|
||||
pDrawList = pDrawListActive;
|
||||
|
||||
pDrawList->AddShadowRect(vecMin, vecMax, colShadow.GetU32(), flThickness, ImVec2(0, 0), roundingCorners, flRounding);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region draw_structures
|
||||
|
||||
void AnimationHandler_t::Update(const float flDeltaTime, const float flDuration)
|
||||
{
|
||||
if (fnEaseIn == nullptr)
|
||||
fnEaseIn = &EASING::InSine;
|
||||
|
||||
if (fnEaseOut == nullptr)
|
||||
fnEaseOut = &EASING::OutSine;
|
||||
|
||||
// Reset the elapsed time if the bool switches
|
||||
if (bSwitch != bLastSwitch)
|
||||
flElapsedTime = 0;
|
||||
|
||||
flElapsedTime = MATH::Max(0.0f, MATH::Min(flElapsedTime, flDuration));
|
||||
float flTime = flElapsedTime / flDuration;
|
||||
|
||||
// Determine the initial and target value based on the current state
|
||||
float flInitialValue = bSwitch ? 0.1f : flValue;
|
||||
float flTargetValue = bSwitch ? 1.0f : 0.1f; /*(1.0f is max value)*/
|
||||
|
||||
// Select the appropriate easing function based on the current state
|
||||
EasingFunction_t fnCurrentEase = bSwitch ? fnEaseIn : fnEaseOut;
|
||||
|
||||
// Apply the appropriate easing function based on fade-in or fade-out (with lerping, which is basically what's the math were doing)
|
||||
flValue = (flInitialValue + (flTargetValue - flInitialValue)) * (float)fnCurrentEase(flTime);
|
||||
flValue = MATH::Clamp(flValue, 0.1f, 1.0f);
|
||||
|
||||
flElapsedTime += flDeltaTime;
|
||||
bLastSwitch = bSwitch;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
@@ -0,0 +1,246 @@
|
||||
#pragma once
|
||||
|
||||
// used: [d3d]
|
||||
#include <d3d11.h>
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
#include "../sdk/datatypes/color.h"
|
||||
#include "../sdk/datatypes/vector.h"
|
||||
#include <mutex>
|
||||
// used: [ext] imgui
|
||||
#include "../../dependencies/imgui/imgui.h"
|
||||
#include "../../dependencies/imgui/imgui_internal.h"
|
||||
|
||||
// forward declarations
|
||||
struct KeyBind_t;
|
||||
|
||||
#pragma region draw_objects_enumerations
|
||||
|
||||
enum ERectRenderFlags : unsigned int
|
||||
{
|
||||
DRAW_RECT_NONE = 0,
|
||||
DRAW_RECT_OUTLINE = (1 << 0),
|
||||
DRAW_RECT_BORDER = (1 << 1),
|
||||
DRAW_RECT_FILLED = (1 << 2)
|
||||
};
|
||||
|
||||
enum ECircleRenderFlags : unsigned int
|
||||
{
|
||||
DRAW_CIRCLE_NONE = 0,
|
||||
DRAW_CIRCLE_OUTLINE = (1 << 0),
|
||||
DRAW_CIRCLE_FILLED = (1 << 1)
|
||||
};
|
||||
|
||||
enum ETriangleRenderFlags : unsigned int
|
||||
{
|
||||
DRAW_TRIANGLE_NONE = 0,
|
||||
DRAW_TRIANGLE_OUTLINE = (1 << 0),
|
||||
DRAW_TRIANGLE_FILLED = (1 << 1)
|
||||
};
|
||||
|
||||
enum EQuadRenderFlags : unsigned int
|
||||
{
|
||||
DRAW_QUAD_NONE = 0,
|
||||
DRAW_QUAD_OUTLINE = (1 << 0),
|
||||
DRAW_QUAD_FILLED = (1 << 1)
|
||||
};
|
||||
|
||||
enum EPolygonRenderFlags : unsigned int
|
||||
{
|
||||
DRAW_POLYGON_NONE = 0,
|
||||
DRAW_POLYGON_OUTLINE = (1 << 0),
|
||||
DRAW_POLYGON_FILLED = (1 << 1)
|
||||
};
|
||||
|
||||
enum ETextRenderFlags : unsigned int
|
||||
{
|
||||
DRAW_TEXT_NONE = 0,
|
||||
DRAW_TEXT_DROPSHADOW = (1 << 0),
|
||||
DRAW_TEXT_OUTLINE = (1 << 1)
|
||||
};
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region draw_structures
|
||||
struct BBox_t {
|
||||
BBox_t() { Invalidate(); }
|
||||
|
||||
void Invalidate() {
|
||||
static constexpr auto MAX_FLOAT = std::numeric_limits<float>::max();
|
||||
|
||||
m_Mins.x = m_Mins.y = MAX_FLOAT;
|
||||
m_Maxs.x = m_Maxs.y = -MAX_FLOAT;
|
||||
|
||||
std::fill(std::begin(m_Vertices), std::end(m_Vertices), ImVec2{ -MAX_FLOAT, -MAX_FLOAT });
|
||||
}
|
||||
|
||||
ImVec2 m_Mins, m_Maxs;
|
||||
ImVec2 m_Vertices[8];
|
||||
};
|
||||
|
||||
// predefined custom user type
|
||||
struct ColorPickerVar_t;
|
||||
|
||||
typedef double (*EasingFunction_t)(double);
|
||||
struct AnimationHandler_t
|
||||
{
|
||||
// default: ease::in/outsine
|
||||
AnimationHandler_t(EasingFunction_t fnIn = nullptr, EasingFunction_t fnOut = nullptr) :
|
||||
fnEaseIn(fnIn), fnEaseOut(fnOut), bSwitch(false), bLastSwitch(false), flElapsedTime(0.f), flValue(0.1f){};
|
||||
~AnimationHandler_t() = default;
|
||||
|
||||
// Has to be called every frame
|
||||
void Update(const float flDeltaTime, const float flDuration);
|
||||
|
||||
// Get the current value multiplied by a scale
|
||||
float GetValue(float flScale = 1.0f)
|
||||
{
|
||||
return flValue * flScale;
|
||||
}
|
||||
|
||||
const bool GetSwitch() const
|
||||
{
|
||||
return bSwitch;
|
||||
}
|
||||
|
||||
// switch state
|
||||
void Switch()
|
||||
{
|
||||
bSwitch = !bSwitch;
|
||||
}
|
||||
|
||||
void SetSwitch(const bool bState)
|
||||
{
|
||||
bSwitch = bState;
|
||||
}
|
||||
|
||||
private:
|
||||
// Set to true for ease-in animation, false for ease-out
|
||||
bool bSwitch = 0;
|
||||
bool bLastSwitch = bSwitch;
|
||||
|
||||
float flElapsedTime = 0.f;
|
||||
|
||||
// Current value of the animation
|
||||
float flValue = 0.1f;
|
||||
|
||||
// Ease in and out functions Declaration
|
||||
EasingFunction_t fnEaseIn = nullptr;
|
||||
EasingFunction_t fnEaseOut = nullptr;
|
||||
};
|
||||
|
||||
#pragma endregion
|
||||
|
||||
/*
|
||||
* FONTS
|
||||
*/
|
||||
namespace FONT
|
||||
{
|
||||
// 0. verdana, size: 12px * scaledDPI(1.0f->2.0f); lighthinting
|
||||
inline ImFont* pMenu[5];
|
||||
inline ImFont* pMenuTabsDesc;
|
||||
// 1. verdana, size: 14px; bold
|
||||
inline ImFont* pExtra;
|
||||
// 2. tahoma, size: 16px; lighthinting
|
||||
inline ImFont* pVisual;
|
||||
|
||||
inline ImFont* pEspName;
|
||||
inline ImFont* pEspFlagsName;
|
||||
inline ImFont* pEspWepName;
|
||||
inline ImFont* pEspHealth;
|
||||
inline ImFont* pEspIcons;
|
||||
inline ImFont* pEspArmor;
|
||||
inline ImFont* gui_icons_font;
|
||||
inline ImFont* isis;
|
||||
inline ImFont* icon_font;
|
||||
inline ImFont* font;
|
||||
inline ImFont* mainfont;
|
||||
inline ImFont* esp;
|
||||
inline ImFont* menuFont;
|
||||
inline ImFont* controlFont;
|
||||
inline ImFont* boldMenuFont;
|
||||
inline ImFont* tabFont;
|
||||
inline ImFont* keybinds;
|
||||
inline ImFont* weaponzFont;
|
||||
inline ImFont* weapon_icons;
|
||||
inline ImFont* museoSans;
|
||||
inline ImFont* roboto;
|
||||
inline ImFont* robotoTitle;
|
||||
inline ImFont* iconsLarge;
|
||||
inline ImFont* weaponIcons;
|
||||
inline ImFont* interfaces;
|
||||
inline ImFont* cs;
|
||||
inline ImFont* cs_huge;
|
||||
}
|
||||
|
||||
// extended imgui functionality
|
||||
namespace ImGui
|
||||
{
|
||||
/* @section: main */
|
||||
void HelpMarker(const char* szDescription);
|
||||
bool HotKey(const char* szLabel, unsigned int* pValue);
|
||||
bool HotKey(const char* szLabel, KeyBind_t* pKeyBind, const bool bAllowSwitch = true);
|
||||
bool MultiCombo(const char* szLabel, unsigned int* pFlags, const char* const* arrItems, int nItemsCount);
|
||||
bool BeginListBox(const char* szLabel, int nItemsCount, int nHeightInItems = -1);
|
||||
|
||||
/* @section: wrappers */
|
||||
bool ColorEdit3(const char* szLabel, Color_t* pColor, ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_DisplayHex);
|
||||
bool ColorEdit4(const char* szLabel, Color_t* pColor, ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_DisplayHex | ImGuiColorEditFlags_AlphaBar, int type = 0);
|
||||
|
||||
bool ColorEdit3(const char* szLabel, ColorPickerVar_t* pColor, ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_DisplayHex);
|
||||
bool ColorEdit4(const char* szLabel, ColorPickerVar_t* pColorVar, ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_DisplayHex | ImGuiColorEditFlags_AlphaBar, int type = 0);
|
||||
}
|
||||
inline std::recursive_mutex input_mutex{ };
|
||||
|
||||
/*
|
||||
* DRAW
|
||||
* - rendering framework
|
||||
*/
|
||||
namespace D
|
||||
{
|
||||
// initialize rendering engine, create fonts, set styles etc
|
||||
bool Setup(HWND hWnd, ID3D11Device* pDevice, ID3D11DeviceContext* pContext);
|
||||
// shutdown rendering engine
|
||||
void Destroy();
|
||||
|
||||
bool InitImGui();
|
||||
void Render();
|
||||
/* @section: callbacks */
|
||||
// handle input window message and save keys states in array
|
||||
bool OnWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
/* @section: get */
|
||||
/// convert world space to screen space coordinates by game's conversion matrix
|
||||
/// @param[out] pvecScreen output for converted screen position
|
||||
/// @returns: true if converted coordinates fit into display size, false otherwise
|
||||
bool WorldToScreen(const Vector_t& in, ImVec2& out);
|
||||
void RenderDrawData(ImDrawData* data);
|
||||
void ResetDrawData();
|
||||
void SwapDrawData();
|
||||
/* @section: some small utils*/
|
||||
Vector_t GetScreenSize();
|
||||
float CalculateDPI(const int nScaleTarget = 0);
|
||||
|
||||
/* @section: bindings */
|
||||
void AddDrawListRect(ImDrawList* pDrawList, const ImVec2& vecMin, const ImVec2& vecMax, const Color_t& colRect, const unsigned int uFlags = DRAW_RECT_NONE, const Color_t& colOutline = Color_t(0, 0, 0, 255), const float flRounding = 0.f, const ImDrawFlags roundingCorners = ImDrawFlags_RoundCornersAll, float flThickness = 1.0f, const float flOutlineThickness = 1.0f);
|
||||
void AddDrawListRectMultiColor(ImDrawList* pDrawList, const ImVec2& vecMin, const ImVec2& vecMax, const Color_t& colUpperLeft, const Color_t& colUpperRight, const Color_t& colBottomRight, const Color_t& colBottomLeft);
|
||||
void AddDrawListCircle(ImDrawList* pDrawList, const ImVec2& vecCenter, const float flRadius, const Color_t& colCircle, const int nSegments, const unsigned int uFlags = DRAW_CIRCLE_NONE, const Color_t& colOutline = Color_t(0, 0, 0, 255), const float flThickness = 1.0f, const float flOutlineThickness = 1.0f);
|
||||
void AddDrawListArc(ImDrawList* pDrawList, const ImVec2& vecPosition, const float flRadius, const float flMinimumAngle, const float flMaximumAngle, const Color_t& colArc = Color_t(255, 255, 255, 255), const float flThickness = 1.0f);
|
||||
void AddDrawListLine(ImDrawList* pDrawList, const ImVec2& vecFirst, const ImVec2& vecSecond, const Color_t& colLine, const float flThickness = 1.0f);
|
||||
void AddDrawListTriangle(ImDrawList* pDrawList, const ImVec2& vecFirst, const ImVec2& vecSecond, const ImVec2& vecThird, const Color_t& colTriangle, const unsigned int uFlags = DRAW_TRIANGLE_NONE, const Color_t& colOutline = Color_t(0, 0, 0, 255), const float flThickness = 0.f);
|
||||
void AddDrawListQuad(ImDrawList* pDrawList, const ImVec2& vecFirst, const ImVec2& vecSecond, const ImVec2& vecThird, const ImVec2& vecFourth, const Color_t& colQuad, const unsigned int uFlags = DRAW_QUAD_NONE, const Color_t& colOutline = Color_t(0, 0, 0, 255), const float flThickness = 0.f);
|
||||
void AddDrawListPolygon(ImDrawList* pDrawList, const ImVec2* vecPoints, const int nPointsCount, const Color_t& colPolygon, unsigned int uFlags = DRAW_POLYGON_NONE, const Color_t& colOutline = Color_t(0, 0, 0, 255), const bool bClosed = true, const float flThickness = 1.0f);
|
||||
void AddDrawListText(ImDrawList* pDrawList, const ImFont* pFont, const ImVec2& vecPosition, const char* szText, const Color_t& colText, const unsigned int uFlags = DRAW_TEXT_NONE, const Color_t& colOutline = Color_t(0, 0, 0, 255), const float flThickness = 1.0f);
|
||||
void AddDrawListShadowRect(ImDrawList* pDrawList, const ImVec2& vecMin, const ImVec2& vecMax, const Color_t& colShadow, float flThickness = 32.f, float flRounding = 0.0f, ImDrawFlags roundingCorners = ImDrawFlags_RoundCornersAll);
|
||||
|
||||
/* @section: values */
|
||||
// rendering engine initialization state
|
||||
inline bool bInitialized = false;
|
||||
// active draw data container used to store
|
||||
inline ImDrawList* pDrawListActive = nullptr;
|
||||
// safe draw data container
|
||||
inline ImDrawList* pDrawListSafe = nullptr;
|
||||
// actual draw data container used to render
|
||||
inline ImDrawList* pDrawListRender = nullptr;
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
#pragma once
|
||||
|
||||
// used: math functions
|
||||
#include "math.h"
|
||||
|
||||
namespace EASING
|
||||
{
|
||||
CS_INLINE double InSine(const double t)
|
||||
{
|
||||
return M_SIN(1.5707963 * t);
|
||||
}
|
||||
|
||||
CS_INLINE double OutSine(double t)
|
||||
{
|
||||
return 1 + M_SIN(1.5707963 * (--t));
|
||||
}
|
||||
|
||||
CS_INLINE double InOutSine(const double t)
|
||||
{
|
||||
return 0.5 * (1 + M_SIN(3.1415926 * (t - 0.5)));
|
||||
}
|
||||
|
||||
CS_INLINE double InQuad(const double t)
|
||||
{
|
||||
return t * t;
|
||||
}
|
||||
|
||||
CS_INLINE double OutQuad(const double t)
|
||||
{
|
||||
return t * (2 - t);
|
||||
}
|
||||
|
||||
CS_INLINE double InOutQuad(const double t)
|
||||
{
|
||||
return t < 0.5 ? 2 * t * t : t * (4 - 2 * t) - 1;
|
||||
}
|
||||
|
||||
CS_INLINE double InCubic(const double t)
|
||||
{
|
||||
return t * t * t;
|
||||
}
|
||||
|
||||
CS_INLINE double OutCubic(double t)
|
||||
{
|
||||
return 1 + (--t) * t * t;
|
||||
}
|
||||
|
||||
CS_INLINE double InOutCubic(double t)
|
||||
{
|
||||
return t < 0.5 ? 4 * t * t * t : 1 + (--t) * (2 * (--t)) * (2 * t);
|
||||
}
|
||||
|
||||
CS_INLINE double InQuart(double t)
|
||||
{
|
||||
t *= t;
|
||||
return t * t;
|
||||
}
|
||||
|
||||
CS_INLINE double OutQuart(double t)
|
||||
{
|
||||
t = (--t) * t;
|
||||
return 1 - t * t;
|
||||
}
|
||||
|
||||
CS_INLINE double InOutQuart(double t)
|
||||
{
|
||||
if (t < 0.5)
|
||||
{
|
||||
t *= t;
|
||||
return 8 * t * t;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = (--t) * t;
|
||||
return 1 - 8 * t * t;
|
||||
}
|
||||
}
|
||||
|
||||
CS_INLINE double InQuint(const double t)
|
||||
{
|
||||
const double t2 = t * t;
|
||||
return t * t2 * t2;
|
||||
}
|
||||
|
||||
CS_INLINE double OutQuint(double t)
|
||||
{
|
||||
const double t2 = (--t) * t;
|
||||
return 1 + t * t2 * t2;
|
||||
}
|
||||
|
||||
CS_INLINE double InOutQuint(double t)
|
||||
{
|
||||
double t2;
|
||||
if (t < 0.5)
|
||||
{
|
||||
t2 = t * t;
|
||||
return 16 * t * t2 * t2;
|
||||
}
|
||||
else
|
||||
{
|
||||
t2 = (--t) * t;
|
||||
return 1 + 16 * t * t2 * t2;
|
||||
}
|
||||
}
|
||||
|
||||
CS_INLINE double InExpo(const double t)
|
||||
{
|
||||
return (M_POW(2.0, 8 * t) - 1) / 255;
|
||||
}
|
||||
|
||||
CS_INLINE double OutExpo(const double t)
|
||||
{
|
||||
return 1 - M_POW(2.0, -8 * t);
|
||||
}
|
||||
|
||||
CS_INLINE double InOutExpo(const double t)
|
||||
{
|
||||
if (t < 0.5)
|
||||
{
|
||||
return (M_POW(2.0, 16 * t) - 1) / 510;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1 - 0.5 * M_POW(2.0, -16 * (t - 0.5));
|
||||
}
|
||||
}
|
||||
|
||||
CS_INLINE double InCirc(const double t)
|
||||
{
|
||||
return 1 - M_SQRT(1 - t);
|
||||
}
|
||||
|
||||
CS_INLINE double OutCirc(const double t)
|
||||
{
|
||||
return M_SQRT(t);
|
||||
}
|
||||
|
||||
CS_INLINE double InOutCirc(const double t)
|
||||
{
|
||||
if (t < 0.5)
|
||||
{
|
||||
return (1 - M_SQRT(1 - 2 * t)) * 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (1 + M_SQRT(2 * t - 1)) * 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
CS_INLINE double InBack(const double t)
|
||||
{
|
||||
return t * t * (2.70158 * t - 1.70158);
|
||||
}
|
||||
|
||||
CS_INLINE double OutBack(double t)
|
||||
{
|
||||
return 1 + (--t) * t * (2.70158 * t + 1.70158);
|
||||
}
|
||||
|
||||
CS_INLINE double InOutBack(double t)
|
||||
{
|
||||
if (t < 0.5)
|
||||
{
|
||||
return t * t * (7 * t - 2.5) * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1 + (--t) * t * 2 * (7 * t + 2.5);
|
||||
}
|
||||
}
|
||||
|
||||
CS_INLINE double InElastic(const double t)
|
||||
{
|
||||
const double t2 = t * t;
|
||||
return t2 * t2 * M_SIN(t * MATH::_PI * 4.5);
|
||||
}
|
||||
|
||||
CS_INLINE double OutElastic(const double t)
|
||||
{
|
||||
const double t2 = (t - 1) * (t - 1);
|
||||
return 1 - t2 * t2 * M_COS(t * MATH::_PI * 4.5);
|
||||
}
|
||||
|
||||
CS_INLINE double InOutElastic(const double t)
|
||||
{
|
||||
double t2;
|
||||
if (t < 0.45)
|
||||
{
|
||||
t2 = t * t;
|
||||
return 8 * t2 * t2 * M_SIN(t * MATH::_PI * 9);
|
||||
}
|
||||
else if (t < 0.55)
|
||||
{
|
||||
return 0.5 + 0.75 * M_SIN(t * MATH::_PI * 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
t2 = (t - 1) * (t - 1);
|
||||
return 1 - 8 * t2 * t2 * M_SIN(t * MATH::_PI * 9);
|
||||
}
|
||||
}
|
||||
|
||||
CS_INLINE double InBounce(const double t)
|
||||
{
|
||||
return M_POW(2.0, 6 * (t - 1)) * M_ABS(M_SIN(t * MATH::_PI * 3.5));
|
||||
}
|
||||
|
||||
CS_INLINE double OutBounce(const double t)
|
||||
{
|
||||
return 1 - M_POW(2.0, -6 * t) * M_ABS(M_COS(t * MATH::_PI * 3.5));
|
||||
}
|
||||
|
||||
CS_INLINE double InOutBounce(const double t)
|
||||
{
|
||||
if (t < 0.5)
|
||||
{
|
||||
return 8 * M_POW(2.0, 8 * (t - 1)) * M_ABS(M_SIN(t * MATH::_PI * 7));
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1 - 8 * M_POW(2.0, -8 * t) * M_ABS(M_SIN(t * MATH::_PI * 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
// used: [stl] uint64_t
|
||||
#include <cstdint>
|
||||
|
||||
// used :CRT::StringLength
|
||||
#include "crt.h"
|
||||
|
||||
using FNV1A_t = std::uint64_t;
|
||||
|
||||
/*
|
||||
* 64-BIT FNV1A HASH
|
||||
*/
|
||||
namespace HASHCNSX {
|
||||
|
||||
constexpr uint32_t val_32_const = 0x811c9dc5;
|
||||
constexpr uint32_t prime_32_const = 0x1000193;
|
||||
|
||||
inline constexpr uint32_t hash_32_fnv1a_const(const char* const str, const uint32_t value = val_32_const) noexcept {
|
||||
return (str[0] == '\0') ? value : hash_32_fnv1a_const(&str[1], (value ^ uint32_t(str[0])) * prime_32_const);
|
||||
}
|
||||
}
|
||||
namespace FNV1A
|
||||
{
|
||||
/* @section: [internal] constants */
|
||||
constexpr FNV1A_t ullBasis = 0xCBF29CE484222325ULL;
|
||||
constexpr FNV1A_t ullPrime = 0x100000001B3ULL;
|
||||
|
||||
/* @section: get */
|
||||
/// @param[in] szString string for which you want to generate a hash
|
||||
/// @param[in] uKey key of hash generation
|
||||
/// @returns: calculated at compile-time hash of given string
|
||||
consteval FNV1A_t HashConst(const char* szString, const FNV1A_t uKey = ullBasis) noexcept
|
||||
{
|
||||
return (szString[0] == '\0') ? uKey : HashConst(&szString[1], (uKey ^ static_cast<FNV1A_t>(szString[0])) * ullPrime);
|
||||
}
|
||||
|
||||
/// @param[in] szString string for which you want to generate a hash
|
||||
/// @param[in] uKey key of hash generation
|
||||
/// @returns: calculated at run-time hash of given string
|
||||
inline FNV1A_t Hash(const char* szString, FNV1A_t uKey = ullBasis) noexcept
|
||||
{
|
||||
const std::size_t nLength = CRT::StringLength(szString);
|
||||
|
||||
for (std::size_t i = 0U; i < nLength; ++i)
|
||||
{
|
||||
uKey ^= szString[i];
|
||||
uKey *= ullPrime;
|
||||
}
|
||||
|
||||
return uKey;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// used: get_x_lparam, get_y_lparam
|
||||
#include <windowsx.h>
|
||||
|
||||
#include "inputsystem.h"
|
||||
|
||||
// used: menu open/panic keys
|
||||
#include "../core/variables.h"
|
||||
// used: wndproc hook
|
||||
#include "../core/hooks.h"
|
||||
// used: menu variables
|
||||
#include "../core/menu.h"
|
||||
// used: iinputsystem
|
||||
#include "../core/interfaces.h"
|
||||
#include "../sdk/interfaces/iinputsystem.h"
|
||||
|
||||
// used: [ext] imrect
|
||||
#include "../dependencies/imgui/imgui_internal.h"
|
||||
#include "../cstrike/core/spoofcall/syscall.h"
|
||||
#include <memory>
|
||||
#include "bcrypt.h"
|
||||
#include "../core/spoofcall/lazy_importer.hpp"
|
||||
static BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam)
|
||||
{
|
||||
const auto MainWindow = [handle]()
|
||||
{
|
||||
return GetWindow(handle, GW_OWNER) == nullptr &&
|
||||
IsWindowVisible(handle) && handle != GetConsoleWindow();
|
||||
};
|
||||
|
||||
DWORD nPID = 0;
|
||||
LI_FN(GetWindowThreadProcessId).safe()(handle, &nPID);
|
||||
|
||||
if (LI_FN(GetCurrentProcessId).safe()() != nPID || !MainWindow())
|
||||
return TRUE;
|
||||
|
||||
*reinterpret_cast<HWND*>(lParam) = handle;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool IPT::Setup()
|
||||
{
|
||||
while (hWindow == nullptr)
|
||||
{
|
||||
EnumWindows(::EnumWindowsCallback, reinterpret_cast<LPARAM>(&hWindow));
|
||||
::Sleep(200U);
|
||||
}
|
||||
|
||||
// change window message handle to our
|
||||
pOldWndProc = reinterpret_cast<WNDPROC>(SetWindowLongPtrW(hWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(H::WndProc)));
|
||||
if (pOldWndProc == nullptr)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void IPT::Destroy()
|
||||
{
|
||||
MENU::bMainWindowOpened = false;
|
||||
::Sleep(200U);
|
||||
|
||||
if (pOldWndProc != nullptr)
|
||||
{
|
||||
SetWindowLongPtrW(hWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(pOldWndProc));
|
||||
pOldWndProc = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool IPT::OnWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
// prevent process when e.g. binding something in-menu
|
||||
if (wParam != C_GET(unsigned int, Vars.nMenuKey) && wParam != C_GET(unsigned int, Vars.nPanicKey) && MENU::bMainWindowOpened)
|
||||
return false;
|
||||
|
||||
// current active key
|
||||
int nKey = 0;
|
||||
// current active key state
|
||||
KeyState_t state = KEY_STATE_NONE;
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
if (wParam < 256U)
|
||||
{
|
||||
nKey = static_cast<int>(wParam);
|
||||
state = KEY_STATE_DOWN;
|
||||
}
|
||||
break;
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
if (wParam < 256U)
|
||||
{
|
||||
nKey = static_cast<int>(wParam);
|
||||
state = KEY_STATE_UP;
|
||||
}
|
||||
break;
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
nKey = VK_LBUTTON;
|
||||
state = uMsg == WM_LBUTTONUP ? KEY_STATE_UP : KEY_STATE_DOWN;
|
||||
break;
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_RBUTTONDBLCLK:
|
||||
nKey = VK_RBUTTON;
|
||||
state = uMsg == WM_RBUTTONUP ? KEY_STATE_UP : KEY_STATE_DOWN;
|
||||
break;
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_MBUTTONDBLCLK:
|
||||
nKey = VK_MBUTTON;
|
||||
state = uMsg == WM_MBUTTONUP ? KEY_STATE_UP : KEY_STATE_DOWN;
|
||||
break;
|
||||
case WM_XBUTTONDOWN:
|
||||
case WM_XBUTTONUP:
|
||||
case WM_XBUTTONDBLCLK:
|
||||
nKey = (GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? VK_XBUTTON1 : VK_XBUTTON2);
|
||||
state = uMsg == WM_XBUTTONUP ? KEY_STATE_UP : KEY_STATE_DOWN;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// save key states
|
||||
if (state == KEY_STATE_UP && arrKeyState[nKey] == KEY_STATE_DOWN) // if swap states it will be pressed state
|
||||
arrKeyState[nKey] = KEY_STATE_RELEASED;
|
||||
else
|
||||
arrKeyState[nKey] = state;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IPT::GetBindState(KeyBind_t& keyBind)
|
||||
{
|
||||
if (keyBind.uKey == 0U)
|
||||
return false;
|
||||
|
||||
switch (keyBind.nMode)
|
||||
{
|
||||
case EKeyBindMode::HOLD:
|
||||
keyBind.bEnable = IsKeyDown(keyBind.uKey);
|
||||
break;
|
||||
case EKeyBindMode::TOGGLE:
|
||||
if (IsKeyReleased(keyBind.uKey))
|
||||
keyBind.bEnable = !keyBind.bEnable;
|
||||
break;
|
||||
}
|
||||
|
||||
return keyBind.bEnable;
|
||||
}
|
||||
|
||||
bool IPT::IsHovered(const ImVec2& vecPosition, const ImVec2& vecSize)
|
||||
{
|
||||
const ImVec2 vecMousePosition = ImGui::GetMousePos();
|
||||
return ImRect(vecPosition, vecPosition + vecSize).Contains(vecMousePosition);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
// used: [win] winapi
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#include "../common.h"
|
||||
// used: keybind_t
|
||||
#include "../core/config.h"
|
||||
|
||||
/*
|
||||
* INPUT SYSTEM
|
||||
* listen and handle key states
|
||||
*/
|
||||
namespace IPT
|
||||
{
|
||||
using KeyState_t = std::uint8_t;
|
||||
|
||||
enum EKeyState : KeyState_t
|
||||
{
|
||||
KEY_STATE_NONE,
|
||||
KEY_STATE_DOWN,
|
||||
KEY_STATE_UP,
|
||||
KEY_STATE_RELEASED
|
||||
};
|
||||
|
||||
/* @section: values */
|
||||
// current window
|
||||
inline HWND hWindow = nullptr;
|
||||
// saved window messages handler
|
||||
inline WNDPROC pOldWndProc = nullptr;
|
||||
// last processed key states
|
||||
inline KeyState_t arrKeyState[256] = {};
|
||||
|
||||
// replace game window messages processor with our
|
||||
bool Setup();
|
||||
// restore window messages processor to original
|
||||
void Destroy();
|
||||
|
||||
/* @section: callbacks */
|
||||
// process input window message and save keys states in array
|
||||
bool OnWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
/* @section: get */
|
||||
/// @returns: true if keybind is active, false otherwise
|
||||
bool GetBindState(KeyBind_t& keyBind);
|
||||
|
||||
[[nodiscard]] bool IsHovered(const ImVec2& vecPosition, const ImVec2& vecSize);
|
||||
|
||||
/// @returns: true if key is being held, false otherwise
|
||||
[[nodiscard]] CS_INLINE bool IsKeyDown(const std::uint32_t uButtonCode)
|
||||
{
|
||||
return arrKeyState[uButtonCode] == KEY_STATE_DOWN;
|
||||
}
|
||||
|
||||
/// @returns: true if key has been just released, false otherwise
|
||||
[[nodiscard]] CS_INLINE bool IsKeyReleased(const std::uint32_t uButtonCode)
|
||||
{
|
||||
if (arrKeyState[uButtonCode] == KEY_STATE_RELEASED)
|
||||
{
|
||||
arrKeyState[uButtonCode] = KEY_STATE_UP;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
// used: [crt] time_t, time, localtime_s
|
||||
#include <ctime>
|
||||
|
||||
#include "log.h"
|
||||
// using: mem_stackalloc, mem_stackfree
|
||||
#include "memory.h"
|
||||
// used: IsPowerOfTwo
|
||||
#include "math.h"
|
||||
// used: GetWorkingPath
|
||||
#include "../core.h"
|
||||
|
||||
// console write stream
|
||||
static HANDLE hConsoleStream = INVALID_HANDLE_VALUE;
|
||||
// file write stream
|
||||
static HANDLE hFileStream = INVALID_HANDLE_VALUE;
|
||||
|
||||
#pragma region log_main
|
||||
bool L::AttachConsole(const wchar_t* wszWindowTitle)
|
||||
{
|
||||
// allocate memory for console
|
||||
if (::AllocConsole() != TRUE)
|
||||
return false;
|
||||
|
||||
// open console output stream
|
||||
if (hConsoleStream = ::CreateFileW(L"CONOUT$", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); hConsoleStream == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
// @test: unnecessary as fas as we don't use std::cout etc
|
||||
if (::SetStdHandle(STD_OUTPUT_HANDLE, hConsoleStream) != TRUE)
|
||||
return false;
|
||||
|
||||
// set console window title
|
||||
if (::SetConsoleTitleW(wszWindowTitle) != TRUE)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void L::DetachConsole()
|
||||
{
|
||||
::CloseHandle(hConsoleStream);
|
||||
|
||||
// free allocated memory for console
|
||||
if (::FreeConsole() != TRUE)
|
||||
return;
|
||||
|
||||
// close console window
|
||||
if (const HWND hConsoleWindow = ::GetConsoleWindow(); hConsoleWindow != nullptr)
|
||||
::PostMessageW(hConsoleWindow, WM_CLOSE, 0U, 0L);
|
||||
}
|
||||
|
||||
bool L::OpenFile(const wchar_t* wszFileName)
|
||||
{
|
||||
wchar_t wszFilePath[MAX_PATH];
|
||||
if (!CORE::GetWorkingPath(wszFilePath))
|
||||
return false;
|
||||
|
||||
CRT::StringCat(wszFilePath, wszFileName);
|
||||
|
||||
// @todo: append time/date to filename and always keep up to 3 files, otherwise delete with lowest date
|
||||
// open file output stream
|
||||
if (hFileStream = ::CreateFileW(wszFilePath, GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); hFileStream == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
// insert UTF-8 BOM
|
||||
::WriteFile(hFileStream, "\xEF\xBB\xBF", 3UL, nullptr, nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void L::CloseFile()
|
||||
{
|
||||
::CloseHandle(hFileStream);
|
||||
}
|
||||
|
||||
void L::WriteMessage(const char* szMessage, const std::size_t nMessageLength)
|
||||
{
|
||||
#ifdef CS_LOG_CONSOLE
|
||||
::WriteConsoleA(hConsoleStream, szMessage, nMessageLength, nullptr, nullptr);
|
||||
#endif
|
||||
#ifdef CS_LOG_FILE
|
||||
::WriteFile(hFileStream, szMessage, nMessageLength, nullptr, nullptr);
|
||||
#endif
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma region log_stream_control
|
||||
L::Stream_t::ColorMarker_t L::SetColor(const LogColorFlags_t nColorFlags)
|
||||
{
|
||||
return { nColorFlags };
|
||||
}
|
||||
|
||||
L::Stream_t::PrecisionMarker_t L::SetPrecision(const int iPrecision)
|
||||
{
|
||||
return { iPrecision };
|
||||
}
|
||||
|
||||
L::Stream_t::ModeMarker_t L::AddFlags(const LogModeFlags_t nModeFlags)
|
||||
{
|
||||
return { nModeFlags };
|
||||
}
|
||||
|
||||
L::Stream_t::ModeMarker_t L::RemoveFlags(const LogModeFlags_t nModeFlags)
|
||||
{
|
||||
return { static_cast<LogModeFlags_t>(nModeFlags | LOG_MODE_REMOVE) };
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
L::Stream_t& L::Stream_t::operator()(const ELogLevel nLevel, const char* szFileBlock)
|
||||
{
|
||||
#if defined(CS_LOG_CONSOLE) || defined(CS_LOG_FILE)
|
||||
// reset previous flags
|
||||
nModeFlags = LOG_MODE_NONE;
|
||||
|
||||
const char* szTypeBlock = nullptr;
|
||||
[[maybe_unused]] LogColorFlags_t nTypeColorFlags = LOG_COLOR_DEFAULT;
|
||||
|
||||
switch (nLevel)
|
||||
{
|
||||
case LOG_INFO:
|
||||
szTypeBlock = "[info] ";
|
||||
nTypeColorFlags = LOG_COLOR_FORE_CYAN;
|
||||
break;
|
||||
case LOG_WARNING:
|
||||
szTypeBlock = "[warning] ";
|
||||
nTypeColorFlags = LOG_COLOR_FORE_YELLOW;
|
||||
break;
|
||||
case LOG_ERROR:
|
||||
szTypeBlock = "[error] ";
|
||||
nTypeColorFlags = LOG_COLOR_FORE_RED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const std::time_t time = std::time(nullptr);
|
||||
std::tm timePoint;
|
||||
localtime_s(&timePoint, &time);
|
||||
|
||||
// @todo: no new line at first use / ghetto af but cheap enough but still ghetto uhhh
|
||||
char szTimeBuffer[32];
|
||||
const std::size_t nTimeSize = CRT::TimeToString(szTimeBuffer, sizeof(szTimeBuffer), "\n[%d-%m-%Y %T] ", &timePoint) - bFirstPrint;
|
||||
|
||||
#ifdef CS_LOG_CONSOLE
|
||||
::SetConsoleTextAttribute(hConsoleStream, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
|
||||
::WriteConsoleA(hConsoleStream, szTimeBuffer + bFirstPrint, nTimeSize, nullptr, nullptr);
|
||||
|
||||
if (szFileBlock != nullptr)
|
||||
{
|
||||
::SetConsoleTextAttribute(hConsoleStream, FOREGROUND_INTENSITY);
|
||||
::WriteConsoleA(hConsoleStream, szFileBlock, CRT::StringLength(szFileBlock), nullptr, nullptr);
|
||||
}
|
||||
|
||||
if (szTypeBlock != nullptr)
|
||||
{
|
||||
::SetConsoleTextAttribute(hConsoleStream, static_cast<WORD>(nTypeColorFlags));
|
||||
::WriteConsoleA(hConsoleStream, szTypeBlock, CRT::StringLength(szTypeBlock), nullptr, nullptr);
|
||||
}
|
||||
|
||||
::SetConsoleTextAttribute(hConsoleStream, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
#endif
|
||||
#ifdef CS_LOG_FILE
|
||||
::WriteFile(hFileStream, szTimeBuffer + bFirstPrint, nTimeSize, nullptr, nullptr);
|
||||
|
||||
char szBlockBuffer[MAX_PATH] = { '\0' };
|
||||
char* szCurrentBlock = szBlockBuffer;
|
||||
|
||||
if (szFileBlock != nullptr)
|
||||
szCurrentBlock = CRT::StringCat(szCurrentBlock, szFileBlock);
|
||||
|
||||
if (szTypeBlock != nullptr)
|
||||
szCurrentBlock = CRT::StringCat(szCurrentBlock, szTypeBlock);
|
||||
|
||||
if (szBlockBuffer[0] != '\0')
|
||||
::WriteFile(hFileStream, szBlockBuffer, static_cast<DWORD>(szCurrentBlock - szBlockBuffer), nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
bFirstPrint = false;
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
L::Stream_t& L::Stream_t::operator<<(const ColorMarker_t colorMarker)
|
||||
{
|
||||
#ifdef CS_LOG_CONSOLE
|
||||
::SetConsoleTextAttribute(hConsoleStream, static_cast<WORD>(colorMarker.nColorFlags));
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
L::Stream_t& L::Stream_t::operator<<(const PrecisionMarker_t precisionMarker)
|
||||
{
|
||||
#if defined(CS_LOG_CONSOLE) || defined(CS_LOG_FILE)
|
||||
this->iPrecision = precisionMarker.iPrecision;
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
L::Stream_t& L::Stream_t::operator<<(const ModeMarker_t modeMarker)
|
||||
{
|
||||
#if defined(CS_LOG_CONSOLE) || defined(CS_LOG_FILE)
|
||||
CS_ASSERT(nModeFlags == 0U || MATH::IsPowerOfTwo(nModeFlags & LOG_MODE_INT_FORMAT_MASK)); // used conflicting format flags
|
||||
|
||||
if (modeMarker.nModeFlags & LOG_MODE_REMOVE)
|
||||
nModeFlags &= ~modeMarker.nModeFlags;
|
||||
else
|
||||
nModeFlags |= modeMarker.nModeFlags;
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
L::Stream_t& L::Stream_t::operator<<(const char* szMessage)
|
||||
{
|
||||
#if defined(CS_LOG_CONSOLE) || defined(CS_LOG_FILE)
|
||||
WriteMessage(szMessage, CRT::StringLength(szMessage));
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
L::Stream_t& L::Stream_t::operator<<(const wchar_t* wszMessage)
|
||||
{
|
||||
#if defined(CS_LOG_CONSOLE) || defined(CS_LOG_FILE)
|
||||
/*
|
||||
* to keep stream orientation always same, convert message to UTF-8
|
||||
*
|
||||
* regarding to C++ standard:
|
||||
* [C++11: 27.4.1/3]:
|
||||
* mixing operations on corresponding wide- and narrow-character streams follows the same semantics as mixing such operations on 'FILE's, as specified in amendation [1] of the ISO C standard
|
||||
*
|
||||
* [1]:
|
||||
* the definition of a stream was changed to include the concept of an orientation for both text and binary streams.
|
||||
* after a stream is associated with a file, but before any operations are performed on the stream, the stream is without orientation.
|
||||
* if a wide-character input or output function is applied to a stream without orientation, the stream becomes wide-oriented.
|
||||
* likewise, if a byte input or output operation is applied to a stream with orientation, the stream becomes byte-oriented.
|
||||
* thereafter, only the 'fwide()' or 'freopen()' functions can alter the orientation of a stream.
|
||||
* byte input/output functions shall not be applied to a wide-oriented stream and wide-character input/output functions shall not be applied to a byte-oriented stream.
|
||||
*/
|
||||
const std::size_t nMessageLength = CRT::StringLengthMultiByte(wszMessage);
|
||||
char* szMessage = static_cast<char*>(MEM_STACKALLOC(nMessageLength + 1U));
|
||||
CRT::StringUnicodeToMultiByte(szMessage, nMessageLength + 1U, wszMessage);
|
||||
|
||||
WriteMessage(szMessage, nMessageLength);
|
||||
|
||||
MEM_STACKFREE(szMessage);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
L::Stream_t& L::Stream_t::operator<<(const bool bValue)
|
||||
{
|
||||
#if defined(CS_LOG_CONSOLE) || defined(CS_LOG_FILE)
|
||||
const char* szBoolean = ((nModeFlags & LOG_MODE_BOOL_ALPHA) ? (bValue ? "true" : "false") : (bValue ? "1" : "0"));
|
||||
const std::size_t nBooleanLength = CRT::StringLength(szBoolean);
|
||||
|
||||
WriteMessage(szBoolean, nBooleanLength);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
#pragma once
|
||||
// used: [win] winapi
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
// using: stringcopy, stringcat, timetostring
|
||||
#include "crt.h"
|
||||
|
||||
// used: sdk datatypes
|
||||
#include "../sdk/datatypes/color.h"
|
||||
#include "../sdk/datatypes/vector.h"
|
||||
#include "../sdk/datatypes/qangle.h"
|
||||
|
||||
// @todo: poorly designed in case we don't need logging at all, xor continues wasteful compilation without any references | add smth like dummystream_t and unreference macro params?
|
||||
|
||||
#pragma region log_definitions
|
||||
#ifdef _DEBUG
|
||||
#if defined(CS_COMPILER_CLANG)
|
||||
#define L_PRINT(LEVEL) L::stream(LEVEL, "[" __FILE_NAME__ ":" CS_STRINGIFY(__LINE__) "] ")
|
||||
#else
|
||||
#define L_PRINT(LEVEL) L::stream(LEVEL, L::DETAIL::MakeFileBlock<CRT::StringLength(L::DETAIL::GetFileName(__FILE__)), CRT::StringLength(CS_STRINGIFY(__LINE__))>(L::DETAIL::GetFileName(__FILE__), CS_STRINGIFY(__LINE__)).Get())
|
||||
#endif
|
||||
#else
|
||||
#define L_PRINT(LEVEL) L::stream(LEVEL)
|
||||
#endif
|
||||
#pragma endregion
|
||||
|
||||
#pragma region log_enumerations
|
||||
|
||||
enum ELogLevel : std::uint8_t
|
||||
{
|
||||
LOG_NONE = 0,
|
||||
LOG_INFO,
|
||||
LOG_WARNING,
|
||||
LOG_ERROR
|
||||
};
|
||||
|
||||
using LogModeFlags_t = std::uint16_t;
|
||||
|
||||
enum ELogModeFlags : LogModeFlags_t
|
||||
{
|
||||
LOG_MODE_NONE = 0U,
|
||||
|
||||
// boolean formatting
|
||||
LOG_MODE_BOOL_ALPHA = (1U << 0U), // switches between textual and numeric representation of booleans
|
||||
|
||||
// integer formatting
|
||||
LOG_MODE_INT_SHOWBASE = (1U << 1U), // switches display of number base prefixes used by C++ literal constants
|
||||
LOG_MODE_INT_FORMAT_HEX = (1U << 2U), // switches integer numbers hexadecimal format
|
||||
LOG_MODE_INT_FORMAT_DEC = (1U << 3U), // switches integer numbers decimal format
|
||||
LOG_MODE_INT_FORMAT_OCT = (1U << 4U), // switches integer numbers octal format
|
||||
LOG_MODE_INT_FORMAT_BIN = (1U << 5U), // switches integer numbers binary format
|
||||
LOG_MODE_INT_FORMAT_MASK = (LOG_MODE_INT_FORMAT_HEX | LOG_MODE_INT_FORMAT_DEC | LOG_MODE_INT_FORMAT_OCT | LOG_MODE_INT_FORMAT_BIN),
|
||||
|
||||
// floating-point formatting
|
||||
LOG_MODE_FLOAT_SHOWPOINT = (1U << 6U), // switches decimal point for those numbers whose decimal part is zero
|
||||
LOG_MODE_FLOAT_FORMAT_HEX = (1U << 7U), // switches floating-point numbers hexadecimal format
|
||||
LOG_MODE_FLOAT_FORMAT_FIXED = (1U << 8U), // switches floating-point numbers formatting in fixed-point notation
|
||||
LOG_MODE_FLOAT_FORMAT_SCIENTIFIC = (1U << 9U), // switches floating-point numbers formatting in scientific notation
|
||||
LOG_MODE_FLOAT_FORMAT_MASK = (LOG_MODE_FLOAT_FORMAT_HEX | LOG_MODE_FLOAT_FORMAT_FIXED | LOG_MODE_FLOAT_FORMAT_SCIENTIFIC),
|
||||
|
||||
// numerical formatting
|
||||
LOG_MODE_NUM_SHOWPOSITIVE = (1U << 10U), // switches display of plus sign '+' in non-negative numbers
|
||||
LOG_MODE_NUM_UPPERCASE = (1U << 11U), // switches uppercase characters in numbers
|
||||
|
||||
/* [internal] */
|
||||
LOG_MODE_REMOVE = (1U << 15U)
|
||||
};
|
||||
|
||||
using LogColorFlags_t = std::uint16_t;
|
||||
|
||||
enum ELogColorFlags : LogColorFlags_t
|
||||
{
|
||||
LOG_COLOR_FORE_BLUE = FOREGROUND_BLUE,
|
||||
LOG_COLOR_FORE_GREEN = FOREGROUND_GREEN,
|
||||
LOG_COLOR_FORE_RED = FOREGROUND_RED,
|
||||
LOG_COLOR_FORE_INTENSITY = FOREGROUND_INTENSITY,
|
||||
LOG_COLOR_FORE_GRAY = FOREGROUND_INTENSITY,
|
||||
LOG_COLOR_FORE_CYAN = FOREGROUND_BLUE | FOREGROUND_GREEN,
|
||||
LOG_COLOR_FORE_MAGENTA = FOREGROUND_BLUE | FOREGROUND_RED,
|
||||
LOG_COLOR_FORE_YELLOW = FOREGROUND_GREEN | FOREGROUND_RED,
|
||||
LOG_COLOR_FORE_BLACK = 0U,
|
||||
LOG_COLOR_FORE_WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
|
||||
|
||||
LOG_COLOR_BACK_BLUE = BACKGROUND_BLUE,
|
||||
LOG_COLOR_BACK_GREEN = BACKGROUND_GREEN,
|
||||
LOG_COLOR_BACK_RED = BACKGROUND_RED,
|
||||
LOG_COLOR_BACK_INTENSITY = BACKGROUND_INTENSITY,
|
||||
LOG_COLOR_BACK_GRAY = BACKGROUND_INTENSITY,
|
||||
LOG_COLOR_BACK_CYAN = BACKGROUND_BLUE | BACKGROUND_GREEN,
|
||||
LOG_COLOR_BACK_MAGENTA = BACKGROUND_BLUE | BACKGROUND_RED,
|
||||
LOG_COLOR_BACK_YELLOW = BACKGROUND_GREEN | BACKGROUND_RED,
|
||||
LOG_COLOR_BACK_BLACK = 0U,
|
||||
LOG_COLOR_BACK_WHITE = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE,
|
||||
|
||||
/* [internal] */
|
||||
LOG_COLOR_DEFAULT = LOG_COLOR_FORE_WHITE | LOG_COLOR_BACK_BLACK
|
||||
};
|
||||
|
||||
#pragma endregion
|
||||
|
||||
/*
|
||||
* LOGGING
|
||||
* - simple logging system with file and console output
|
||||
* used for debugging and fetching values/errors at run-time
|
||||
* @todo: currently not thread safe and can mess messages when used from different threads
|
||||
*/
|
||||
namespace L
|
||||
{
|
||||
namespace DETAIL
|
||||
{
|
||||
// @todo: constructs string per-byte in the stack, how do we can optimize this?
|
||||
template <std::size_t N>
|
||||
struct FileBlockStorage_t
|
||||
{
|
||||
template <std::size_t... I1, std::size_t... I2>
|
||||
consteval explicit FileBlockStorage_t(const char* szFileName, const char* szLineNumber, std::index_sequence<I1...>, std::index_sequence<I2...>) :
|
||||
szStorage{ '[', szFileName[I1]..., ':', szLineNumber[I2]..., ']', ' ', '\0' } { }
|
||||
|
||||
[[nodiscard]] constexpr const char* Get() const
|
||||
{
|
||||
return szStorage;
|
||||
}
|
||||
|
||||
const char szStorage[N + 5U];
|
||||
};
|
||||
|
||||
// fail-free version of 'StringCharR'
|
||||
consteval const char* GetFileName(const char* szFilePath)
|
||||
{
|
||||
const char* szLastPath = szFilePath;
|
||||
|
||||
do
|
||||
{
|
||||
if (*szFilePath == '\\')
|
||||
szLastPath = szFilePath + 1U;
|
||||
} while (*szFilePath++ != '\0');
|
||||
|
||||
return szLastPath;
|
||||
}
|
||||
|
||||
// helper to generate file info block for logging message at compile-time
|
||||
template <std::size_t N1, std::size_t N2>
|
||||
consteval auto MakeFileBlock(const char* szFileName, const char* szFileNumber) noexcept
|
||||
{
|
||||
return FileBlockStorage_t<N1 + N2>(szFileName, szFileNumber, std::make_index_sequence<N1>{}, std::make_index_sequence<N2>{});
|
||||
}
|
||||
}
|
||||
|
||||
/* @section: main */
|
||||
// attach console to current window with write permission and given title
|
||||
bool AttachConsole(const wchar_t* wszWindowTitle);
|
||||
// close write streams and detach console from current window
|
||||
void DetachConsole();
|
||||
// open logging output file
|
||||
bool OpenFile(const wchar_t* wszFileName);
|
||||
// close logging output file
|
||||
void CloseFile();
|
||||
// write message to the file or/and console
|
||||
void WriteMessage(const char* szMessage, const std::size_t nMessageLength);
|
||||
|
||||
// alternative of C++ 'std::cout' and other STL-like streams logging scheme
|
||||
// @todo: is it faster to constantly call 'WriteMessage' instead of concatenating all of the output and print once? i dont think so, due to additional allocations, thread-safe requirements, conditions when we still should call print due to color/etc changes | but generally this should lead to better inlining and less complicated compiled code
|
||||
struct Stream_t
|
||||
{
|
||||
// special unique return type markers to determine and handle change of those flags, just a snap for compile-time, inlined as underlying types at run-time
|
||||
struct ColorMarker_t
|
||||
{
|
||||
LogColorFlags_t nColorFlags;
|
||||
};
|
||||
|
||||
struct PrecisionMarker_t
|
||||
{
|
||||
int iPrecision;
|
||||
};
|
||||
|
||||
struct ModeMarker_t
|
||||
{
|
||||
LogModeFlags_t nModeFlags;
|
||||
};
|
||||
|
||||
// begin of each log message, puts time, file & line, level blocks
|
||||
Stream_t& operator()(const ELogLevel nLevel, const char* szFileBlock = nullptr);
|
||||
|
||||
// manipulators
|
||||
Stream_t& operator<<(ColorMarker_t);
|
||||
Stream_t& operator<<(PrecisionMarker_t);
|
||||
Stream_t& operator<<(ModeMarker_t);
|
||||
// message
|
||||
Stream_t& operator<<(const char* szMessage);
|
||||
Stream_t& operator<<(const wchar_t* wszMessage);
|
||||
// conversion
|
||||
Stream_t& operator<<(const bool bValue);
|
||||
|
||||
template <typename T> requires std::is_integral_v<T>
|
||||
Stream_t& operator<<(const T value)
|
||||
{
|
||||
#if defined(CS_LOG_CONSOLE) || defined(CS_LOG_FILE)
|
||||
int iBase = 10;
|
||||
const char* szPrefix = nullptr;
|
||||
|
||||
if (nModeFlags & LOG_MODE_INT_FORMAT_HEX)
|
||||
{
|
||||
iBase = 16;
|
||||
szPrefix = "0x";
|
||||
}
|
||||
else if (nModeFlags & LOG_MODE_INT_FORMAT_OCT)
|
||||
iBase = 8;
|
||||
else if (nModeFlags & LOG_MODE_INT_FORMAT_BIN)
|
||||
{
|
||||
iBase = 2;
|
||||
szPrefix = "0b";
|
||||
}
|
||||
|
||||
// @todo: LOG_MODE_NUM_UPPERCASE not handled
|
||||
char szIntegerBuffer[CRT::IntegerToString_t<std::int64_t, 2U>::MaxCount() + 2U];
|
||||
char* szInteger = CRT::IntegerToString(value, szIntegerBuffer + 2U, sizeof(szIntegerBuffer) - 2U, iBase);
|
||||
|
||||
// @todo: after int2str rework could be simplified | or completely replaced with strformat
|
||||
if (szPrefix != nullptr && (nModeFlags & LOG_MODE_INT_SHOWBASE))
|
||||
{
|
||||
*--szInteger = szPrefix[1];
|
||||
*--szInteger = szPrefix[0];
|
||||
}
|
||||
|
||||
if constexpr (std::is_signed_v<T>)
|
||||
{
|
||||
if (value >= 0 && (nModeFlags & LOG_MODE_NUM_SHOWPOSITIVE))
|
||||
*--szInteger = '+';
|
||||
}
|
||||
|
||||
const std::size_t nIntegerLength = szIntegerBuffer + sizeof(szIntegerBuffer) - szInteger - 1;
|
||||
WriteMessage(szInteger, nIntegerLength);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T> requires std::is_floating_point_v<T>
|
||||
Stream_t& operator<<(const T value)
|
||||
{
|
||||
#if defined(CS_LOG_CONSOLE) || defined(CS_LOG_FILE)
|
||||
//static_assert((nModeFlags & (LOG_MODE_FLOAT_FORMAT_FIXED | LOG_MODE_FLOAT_FORMAT_SCIENTIFIC)) && std::is_same_v<T, float>); // expected 'double' or 'long double'
|
||||
int iDesiredPrecision = /*((nModeFlags & (LOG_MODE_FLOAT_FORMAT_FIXED | LOG_MODE_FLOAT_FORMAT_SCIENTIFIC)) ? -1 : (*/ iPrecision > 0 ? iPrecision : FLT_DIG; //));
|
||||
|
||||
char szFormatBuffer[8];
|
||||
char* szFormat = szFormatBuffer;
|
||||
*szFormat++ = '%';
|
||||
|
||||
if (nModeFlags & LOG_MODE_NUM_SHOWPOSITIVE)
|
||||
*szFormat++ = '+';
|
||||
|
||||
if (nModeFlags & LOG_MODE_FLOAT_SHOWPOINT)
|
||||
*szFormat++ = '#';
|
||||
|
||||
*szFormat++ = '.';
|
||||
*szFormat++ = '*';
|
||||
if constexpr (std::is_same_v<T, long double>)
|
||||
*szFormat++ = 'L';
|
||||
|
||||
if (nModeFlags & LOG_MODE_FLOAT_FORMAT_FIXED)
|
||||
*szFormat++ = 'f';
|
||||
else
|
||||
{
|
||||
const bool bIsUpperCase = (nModeFlags & LOG_MODE_NUM_UPPERCASE);
|
||||
|
||||
if (nModeFlags & LOG_MODE_FLOAT_FORMAT_HEX)
|
||||
*szFormat++ = bIsUpperCase ? 'A' : 'a';
|
||||
else if (nModeFlags & LOG_MODE_FLOAT_FORMAT_SCIENTIFIC)
|
||||
*szFormat++ = bIsUpperCase ? 'E' : 'e';
|
||||
else
|
||||
*szFormat++ = bIsUpperCase ? 'G' : 'g';
|
||||
}
|
||||
*szFormat = '\0';
|
||||
|
||||
char szFloatBuffer[96];
|
||||
const int nFloatLength = CRT::StringPrintN(szFloatBuffer, sizeof(szFloatBuffer), szFormatBuffer, iDesiredPrecision, value);
|
||||
|
||||
WriteMessage(szFloatBuffer, nFloatLength);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
Stream_t& operator<<(const Vector_t& vecValue)
|
||||
{
|
||||
this->nModeFlags |= LOG_MODE_FLOAT_FORMAT_FIXED;
|
||||
this->iPrecision = 3;
|
||||
*this << CS_XOR("vector3d: (") << vecValue.x << CS_XOR(" | ") << vecValue.y << CS_XOR(" | ") << vecValue.z << CS_XOR(")");
|
||||
return *this;
|
||||
}
|
||||
|
||||
Stream_t& operator<<(const QAngle_t& angValue)
|
||||
{
|
||||
this->nModeFlags |= LOG_MODE_FLOAT_FORMAT_FIXED;
|
||||
this->iPrecision = 3;
|
||||
*this << CS_XOR("qangle: (") << angValue.x << CS_XOR(" | ") << angValue.y << CS_XOR(" | ") << angValue.z << CS_XOR(")");
|
||||
return *this;
|
||||
}
|
||||
|
||||
Stream_t& operator<<(const Color_t& colValue)
|
||||
{
|
||||
*this << CS_XOR("color: (") << static_cast<int>(colValue.r) << CS_XOR(" | ") << static_cast<int>(colValue.g) << CS_XOR(" | ") << static_cast<int>(colValue.b) << CS_XOR(" | ") << static_cast<int>(colValue.a) << CS_XOR(")");
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool bFirstPrint = true;
|
||||
int iPrecision = 0;
|
||||
LogModeFlags_t nModeFlags = LOG_MODE_NONE;
|
||||
};
|
||||
|
||||
/* @section: stream control */
|
||||
// set console color flags for current stream, will reset on next message
|
||||
Stream_t::ColorMarker_t SetColor(const LogColorFlags_t nColorFlags);
|
||||
// set the decimal precision to be used to format floating-point values for current stream, will reset on next message
|
||||
Stream_t::PrecisionMarker_t SetPrecision(const int m_iPrecision);
|
||||
// add logging mode flags for current stream, will reset on next message
|
||||
Stream_t::ModeMarker_t AddFlags(const LogModeFlags_t m_nModeFlags);
|
||||
// remove logging mode flags for current stream
|
||||
Stream_t::ModeMarker_t RemoveFlags(const LogModeFlags_t m_nModeFlags);
|
||||
|
||||
/* @section: values */
|
||||
// primary logging stream
|
||||
inline Stream_t stream;
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
#include "math.h"
|
||||
|
||||
//used: getexportaddr
|
||||
#include "memory.h"
|
||||
#include "../core/sdk.h"
|
||||
#include <imgui/imgui_internal.h>
|
||||
bool MATH::Setup()
|
||||
{
|
||||
bool bSuccess = true;
|
||||
|
||||
const void* hTier0Lib = MEM::GetModuleBaseHandle(TIER0_DLL);
|
||||
if (hTier0Lib == nullptr)
|
||||
return false;
|
||||
|
||||
fnRandomSeed = reinterpret_cast<decltype(fnRandomSeed)>(MEM::GetExportAddress(hTier0Lib, CS_XOR("RandomSeed")));
|
||||
bSuccess &= (fnRandomSeed != nullptr);
|
||||
|
||||
fnRandomFloat = reinterpret_cast<decltype(fnRandomFloat)>(MEM::GetExportAddress(hTier0Lib, CS_XOR("RandomFloat")));
|
||||
bSuccess &= (fnRandomFloat != nullptr);
|
||||
|
||||
fnRandomFloatExp = reinterpret_cast<decltype(fnRandomFloatExp)>(MEM::GetExportAddress(hTier0Lib, CS_XOR("RandomFloatExp")));
|
||||
bSuccess &= (fnRandomFloatExp != nullptr);
|
||||
|
||||
fnRandomInt = reinterpret_cast<decltype(fnRandomInt)>(MEM::GetExportAddress(hTier0Lib, CS_XOR("RandomInt")));
|
||||
bSuccess &= (fnRandomInt != nullptr);
|
||||
|
||||
fnRandomGaussianFloat = reinterpret_cast<decltype(fnRandomGaussianFloat)>(MEM::GetExportAddress(hTier0Lib, CS_XOR("RandomGaussianFloat")));
|
||||
bSuccess &= (fnRandomGaussianFloat != nullptr);
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
// distance between to line segments
|
||||
float MATH::segment_dist(Vector_t start1, Vector_t end1, Vector_t start2, Vector_t end2) noexcept {
|
||||
Vector_t u = end1 - start1;
|
||||
Vector_t v = end2 - start2;
|
||||
Vector_t w = start1 - start2;
|
||||
float a = u.DotProduct(u);
|
||||
float b = u.DotProduct(v);
|
||||
float c = v.DotProduct(v);
|
||||
float d = u.DotProduct(w);
|
||||
float e = v.DotProduct(w);
|
||||
float D = a * c - b * b;
|
||||
float sc, sN, sD = D;
|
||||
float tc, tN, tD = D;
|
||||
|
||||
if (D < 0.001f) {
|
||||
sN = 0.0f;
|
||||
sD = 1.0f;
|
||||
tN = e;
|
||||
tD = c;
|
||||
}
|
||||
else {
|
||||
sN = (b * e - c * d);
|
||||
tN = (a * e - b * d);
|
||||
if (sN < 0.0f) {
|
||||
sN = 0.0f;
|
||||
tN = e;
|
||||
tD = c;
|
||||
}
|
||||
else if (sN > sD) {
|
||||
sN = sD;
|
||||
tN = e + b;
|
||||
tD = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (tN < 0.0f) {
|
||||
tN = 0.0f;
|
||||
|
||||
if (-d < 0.0f) {
|
||||
sN = 0.0f;
|
||||
}
|
||||
else if (-d > a) {
|
||||
sN = sD;
|
||||
}
|
||||
else {
|
||||
sN = -d;
|
||||
sD = a;
|
||||
}
|
||||
}
|
||||
else if (tN > tD) {
|
||||
tN = tD;
|
||||
|
||||
if ((-d + b) < 0.0f) {
|
||||
sN = 0;
|
||||
}
|
||||
else if ((-d + b) > a) {
|
||||
sN = sD;
|
||||
}
|
||||
else {
|
||||
sN = (-d + b);
|
||||
sD = a;
|
||||
}
|
||||
}
|
||||
|
||||
sc = (std::abs(sN) < 0.001f ? 0.0f : sN / sD);
|
||||
tc = (std::abs(tN) < 0.001f ? 0.0f : tN / tD);
|
||||
|
||||
Vector_t dP = w + (u * sc) - (v * tc);
|
||||
return dP.Length();
|
||||
}
|
||||
void MATH::TransformAABB(const Matrix3x4a_t& transform, const Vector_t& minsIn, const Vector_t& maxsIn, Vector_t& minsOut, Vector_t& maxsOut) {
|
||||
const Vector_t localCenter = (minsIn + maxsIn) * 0.5f;
|
||||
const Vector_t& localExtent = maxsIn - localCenter;
|
||||
|
||||
const auto& mat = transform.arrData;
|
||||
const Vector_t worldAxisX{ mat[0][0], mat[0][1], mat[0][2] };
|
||||
const Vector_t worldAxisY{ mat[1][0], mat[1][1], mat[1][2] };
|
||||
const Vector_t worldAxisZ{ mat[2][0], mat[2][1], mat[2][2] };
|
||||
|
||||
const Vector_t worldCenter = localCenter.Transform(transform);
|
||||
const Vector_t worldExtent{
|
||||
localExtent.DotProduct(worldAxisX),
|
||||
localExtent.DotProduct(worldAxisY),
|
||||
localExtent.DotProduct(worldAxisZ),
|
||||
};
|
||||
|
||||
minsOut = worldCenter - worldExtent;
|
||||
maxsOut = worldCenter + worldExtent;
|
||||
}
|
||||
#include <numbers>
|
||||
|
||||
void MATH::angle_vector(const QAngle_t& angles, Vector_t& forward) noexcept {
|
||||
const float x = angles.x * std::numbers::pi_v<float> / 180.f;
|
||||
const float y = angles.y * std::numbers::pi_v<float> / 180.f;
|
||||
const float sp = std::sin(x);
|
||||
const float cp = std::cos(x);
|
||||
const float sy = std::sin(y);
|
||||
const float cy = std::cos(y);
|
||||
forward.x = cp * cy;
|
||||
forward.y = cp * sy;
|
||||
forward.z = -sp;
|
||||
}
|
||||
|
||||
Vector_t MATH::angle_vector(const QAngle_t& angles) noexcept {
|
||||
Vector_t forward;
|
||||
angle_vector(angles, forward);
|
||||
return forward;
|
||||
}
|
||||
|
||||
void MATH::anglevectors(const QAngle_t& angles, Vector_t* forward, Vector_t* right, Vector_t* up )
|
||||
{
|
||||
float cp = std::cos(M_DEG2RAD(angles.x)), sp = std::sin(M_DEG2RAD(angles.x));
|
||||
float cy = std::cos(M_DEG2RAD(angles.y)), sy = std::sin(M_DEG2RAD(angles.y));
|
||||
float cr = std::cos(M_DEG2RAD(angles.z)), sr = std::sin(M_DEG2RAD(angles.z));
|
||||
|
||||
if (forward) {
|
||||
forward->x = cp * cy;
|
||||
forward->y = cp * sy;
|
||||
forward->z = -sp;
|
||||
}
|
||||
|
||||
if (right) {
|
||||
right->x = -1.f * sr * sp * cy + -1.f * cr * -sy;
|
||||
right->y = -1.f * sr * sp * sy + -1.f * cr * cy;
|
||||
right->z = -1.f * sr * cp;
|
||||
}
|
||||
|
||||
if (up) {
|
||||
up->x = cr * sp * cy + -sr * -sy;
|
||||
up->y = cr * sp * sy + -sr * cy;
|
||||
up->z = cr * cp;
|
||||
}
|
||||
}
|
||||
|
||||
void MATH::VectorAngless(const Vector_t& forward, QAngle_t& angles, Vector_t* up) {
|
||||
Vector_t left;
|
||||
float len, up_z, pitch, yaw, roll;
|
||||
|
||||
// get 2d length.
|
||||
len = forward.Length2D();
|
||||
|
||||
if (up && len > 0.001f) {
|
||||
pitch = M_RAD2DEG(std::atan2(-forward.z, len));
|
||||
yaw = M_RAD2DEG(std::atan2(forward.y, forward.x));
|
||||
|
||||
// get left direction vector using cross product.
|
||||
left = (*up).CrossProduct(forward).Normalized();
|
||||
|
||||
// calculate up_z.
|
||||
up_z = (left.y * forward.x) - (left.x * forward.y);
|
||||
|
||||
// calculate roll.
|
||||
roll = M_RAD2DEG(std::atan2(left.z, up_z));
|
||||
}
|
||||
|
||||
else {
|
||||
if (len > 0.f) {
|
||||
// calculate pitch and yaw.
|
||||
pitch = M_RAD2DEG(std::atan2(-forward.z, len));
|
||||
yaw = M_RAD2DEG(std::atan2(forward.y, forward.x));
|
||||
roll = 0.f;
|
||||
}
|
||||
|
||||
else {
|
||||
pitch = (forward.z > 0.f) ? -90.f : 90.f;
|
||||
yaw = 0.f;
|
||||
roll = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
// set out angles.
|
||||
angles = { pitch, yaw, roll };
|
||||
}
|
||||
|
||||
bool MATH::WorldToScreen(const Vector_t& in, ImVec2& out) {
|
||||
if (!ImGui::GetCurrentContext()) return false;
|
||||
|
||||
auto z = SDK::ViewMatrix[3][0] * in.x + SDK::ViewMatrix[3][1] * in.y +
|
||||
SDK::ViewMatrix[3][2] * in.z + SDK::ViewMatrix[3][3];
|
||||
|
||||
if (z < 0.001f)
|
||||
return false;
|
||||
|
||||
out = { (ImGui::GetIO().DisplaySize.x * 0.5f), (ImGui::GetIO().DisplaySize.y * 0.5f) };
|
||||
out.x *= 1.0f + (SDK::ViewMatrix[0][0] * in.x + SDK::ViewMatrix[0][1] * in.y +
|
||||
SDK::ViewMatrix[0][2] * in.z + SDK::ViewMatrix[0][3]) /
|
||||
z;
|
||||
out.y *= 1.0f - (SDK::ViewMatrix[1][0] * in.x + SDK::ViewMatrix[1][1] * in.y +
|
||||
SDK::ViewMatrix[1][2] * in.z + SDK::ViewMatrix[1][3]) /
|
||||
z;
|
||||
|
||||
out = { out.x, out.y };
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
#pragma once
|
||||
|
||||
#include "../common.h"
|
||||
// used: std::is_integral_v
|
||||
#include <type_traits>
|
||||
// used: sin, cos, pow, abs, sqrt
|
||||
#include <corecrt_math.h>// used: MATH::Sin, cos, MATH::Pow, abs, sqrt
|
||||
#include <corecrt_math.h>
|
||||
// used: rand, srand
|
||||
#include <cstdlib>
|
||||
// used: time
|
||||
#include <ctime>
|
||||
#include <imgui/imgui.h>
|
||||
#include "../sdk/datatypes/matrix.h"
|
||||
#include "../sdk/datatypes/vector.h"
|
||||
#include "../sdk/datatypes/qangle.h"
|
||||
// convert angle in degrees to radians
|
||||
#define M_DEG2RAD(DEGREES) ((DEGREES) * (MATH::_PI / 180.f))
|
||||
// convert angle in radians to degrees
|
||||
#define M_RAD2DEG(RADIANS) ((RADIANS) * (180.f / MATH::_PI))
|
||||
/// linearly interpolate the value between @a'X0' and @a'X1' by @a'FACTOR'
|
||||
#define M_LERP(X0, X1, FACTOR) ((X0) + ((X1) - (X0)) * (FACTOR))
|
||||
/// trigonometry
|
||||
#define M_COS(ANGLE) cos(ANGLE)
|
||||
#define M_SIN(ANGLE) sin(ANGLE)
|
||||
#define M_TAN(ANGLE) tan(ANGLE)
|
||||
/// power
|
||||
#define M_POW(BASE, EXPONENT) pow(BASE, EXPONENT)
|
||||
/// absolute value
|
||||
#define M_ABS(VALUE) abs(VALUE)
|
||||
/// square root
|
||||
#define M_SQRT(VALUE) sqrt(VALUE)
|
||||
/// floor
|
||||
#define M_FLOOR(VALUE) floor(VALUE)
|
||||
constexpr auto RadPi = 3.14159265358979323846;
|
||||
constexpr auto DegPi = 180.0;
|
||||
template<typename T>
|
||||
T ToDegrees(T radians) {
|
||||
return (radians * (static_cast<T>(DegPi) / static_cast<T>(RadPi)));
|
||||
}
|
||||
/*
|
||||
* MATHEMATICS
|
||||
* - basic trigonometry, algebraic mathematical functions and constants
|
||||
*/
|
||||
namespace MATH
|
||||
{
|
||||
/* @section: constants */
|
||||
// pi value
|
||||
inline constexpr float _PI = 3.141592654f;
|
||||
// double of pi
|
||||
inline constexpr float _2PI = 6.283185307f;
|
||||
// half of pi
|
||||
inline constexpr float _HPI = 1.570796327f;
|
||||
// quarter of pi
|
||||
inline constexpr float _QPI = 0.785398163f;
|
||||
// reciprocal of double of pi
|
||||
inline constexpr float _1DIV2PI = 0.159154943f;
|
||||
// golden ratio
|
||||
inline constexpr float _PHI = 1.618033988f;
|
||||
bool WorldToScreen(const Vector_t& in, ImVec2& out);
|
||||
|
||||
// capture game's exports
|
||||
bool Setup();
|
||||
|
||||
void TransformAABB(const Matrix3x4a_t& transform, const Vector_t& minsIn, const Vector_t& maxsIn, Vector_t& minsOut, Vector_t& maxsOut);
|
||||
|
||||
void angle_vector(const QAngle_t& angles, Vector_t& forward) noexcept;
|
||||
|
||||
Vector_t angle_vector(const QAngle_t& angles) noexcept;
|
||||
|
||||
float segment_dist(Vector_t start1, Vector_t end1, Vector_t start2, Vector_t end2) noexcept;
|
||||
|
||||
/* @section: algorithm */
|
||||
/// alternative of 'std::min'
|
||||
/// @returns : minimal value of the given comparable values
|
||||
template <typename T>
|
||||
[[nodiscard]] CS_INLINE constexpr const T& Min(const T& left, const T& right) noexcept
|
||||
{
|
||||
return (right < left) ? right : left;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
CS_INLINE T clamp(const T& n, const T& lower, const T& upper)
|
||||
{
|
||||
return std::max(lower, std::min(n, upper));
|
||||
}
|
||||
|
||||
/// alternative of 'std::max'
|
||||
/// @returns : maximal value of the given comparable values
|
||||
template <typename T>
|
||||
[[nodiscard]] CS_INLINE constexpr const T& Max(const T& left, const T& right) noexcept
|
||||
{
|
||||
return (right > left) ? right : left;
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] CS_INLINE float normalize_yaw(float yaw) noexcept
|
||||
{
|
||||
while (yaw > 180.0f)
|
||||
yaw -= 360.0f;
|
||||
|
||||
while (yaw < -180.0f)
|
||||
yaw += 360.0f;
|
||||
|
||||
return yaw;
|
||||
}
|
||||
/// alternative of 'std::clamp'
|
||||
/// @returns : value clamped in range ['minimal' .. 'maximal']
|
||||
template <typename T>
|
||||
[[nodiscard]] CS_INLINE constexpr const T& Clamp(const T& value, const T& minimal, const T& maximal) noexcept
|
||||
{
|
||||
return (value < minimal) ? minimal : (value > maximal) ? maximal :
|
||||
value;
|
||||
}
|
||||
|
||||
|
||||
void anglevectors(const QAngle_t& angles, Vector_t* forward, Vector_t* right = nullptr, Vector_t* up = nullptr);
|
||||
|
||||
void VectorAngless(const Vector_t& forward, QAngle_t& angles, Vector_t* up = nullptr);
|
||||
|
||||
[[nodiscard]] inline void vec_angles(Vector_t forward, Vector_t* angles)
|
||||
{
|
||||
float tmp, yaw, pitch;
|
||||
|
||||
if (forward.y == 0.f && forward.x == 0.f) {
|
||||
yaw = 0;
|
||||
if (forward.z > 0) {
|
||||
pitch = 270;
|
||||
}
|
||||
else {
|
||||
pitch = 90.f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
yaw = (float)(atan2(forward.y, forward.x) * 180.f / 3.14159265358979323846f);
|
||||
if (yaw < 0) {
|
||||
yaw += 360.f;
|
||||
}
|
||||
tmp = (float)sqrt(forward.x * forward.x + forward.y * forward.y);
|
||||
pitch = (float)(atan2(-forward.z, tmp) * 180.f / 3.14159265358979323846f);
|
||||
if (pitch < 0) {
|
||||
pitch += 360.f;
|
||||
}
|
||||
}
|
||||
angles->x = pitch;
|
||||
angles->y = yaw;
|
||||
angles->z = 0.f;
|
||||
}
|
||||
|
||||
/* @section: exponential */
|
||||
/// @returns: true if given number is power of two, false otherwise
|
||||
template <typename T> requires (std::is_integral_v<T>)
|
||||
[[nodiscard]] CS_INLINE constexpr bool IsPowerOfTwo(const T value) noexcept
|
||||
{
|
||||
return value != 0 && (value & (value - 1)) == 0;
|
||||
}
|
||||
|
||||
__forceinline float AngleNormalize(float angle)
|
||||
{
|
||||
angle = fmodf(angle, 360.0f);
|
||||
if (angle > 180)
|
||||
{
|
||||
angle -= 360;
|
||||
}
|
||||
if (angle < -180)
|
||||
{
|
||||
angle += 360;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
/* @section: random using game's exports */
|
||||
inline int(CS_CDECL* fnRandomSeed)(int iSeed) = nullptr;
|
||||
inline float(CS_CDECL* fnRandomFloat)(float flMinValue, float flMaxValue) = nullptr;
|
||||
inline float(CS_CDECL* fnRandomFloatExp)(float flMinValue, float flMaxValue, float flExponent) = nullptr;
|
||||
inline int(CS_CDECL* fnRandomInt)(int iMinValue, int iMaxValue) = nullptr;
|
||||
inline float(CS_CDECL* fnRandomGaussianFloat)(float flMean, float flStdDev) = nullptr;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,515 @@
|
||||
// used: __readfsdword
|
||||
#include <intrin.h>
|
||||
// used: d3d11
|
||||
#include <d3d11.h>
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
// used: l_print
|
||||
#include "log.h"
|
||||
// used: chartohexint
|
||||
#include "crt.h"
|
||||
// used: pe64
|
||||
#include "pe64.h"
|
||||
#include "../core/spoofcall/invoker.h"
|
||||
#include "../core/spoofcall/lazy_importer.hpp"
|
||||
|
||||
bool MEM::Setup()
|
||||
{
|
||||
bool bSuccess = true;
|
||||
|
||||
const void* hSDL3 = spoof_call<void*>(_fake_addr, &GetModuleBaseHandle, SDL3_DLL);
|
||||
const void* hDbgHelp = spoof_call<void*>(_fake_addr, &GetModuleBaseHandle, DBGHELP_DLL);
|
||||
const void* hTier0 = GetModuleBaseHandle(TIER0_DLL);
|
||||
|
||||
if (hSDL3 == nullptr || hDbgHelp == nullptr)
|
||||
return false;
|
||||
|
||||
fnUnDecorateSymbolName = reinterpret_cast<decltype(fnUnDecorateSymbolName)>(GetExportAddress(hDbgHelp, CS_XOR("UnDecorateSymbolName")));
|
||||
bSuccess &= (fnUnDecorateSymbolName != nullptr);
|
||||
|
||||
fnSetRelativeMouseMode = reinterpret_cast<decltype(fnSetRelativeMouseMode)>(GetExportAddress(hSDL3, "SDL_SetRelativeMouseMode"));
|
||||
bSuccess &= (fnSetRelativeMouseMode != nullptr);
|
||||
|
||||
fnSetWindowGrab = reinterpret_cast<decltype(fnSetWindowGrab)>(GetExportAddress(hSDL3, "SDL_SetWindowGrab"));
|
||||
bSuccess &= (fnSetWindowGrab != nullptr);
|
||||
|
||||
fnWarpMouseInWindow = reinterpret_cast<decltype(fnWarpMouseInWindow)>(GetExportAddress(hSDL3, "SDL_WarpMouseInWindow"));
|
||||
bSuccess &= (fnWarpMouseInWindow != nullptr);
|
||||
L_PRINT(LOG_INFO) << CS_XOR("[Memory] Loaded fnWarpMouseInWindow");
|
||||
|
||||
fnCreateMaterial = reinterpret_cast<decltype(fnCreateMaterial)>(FindPattern(MATERIAL_SYSTEM2_DLL, CS_XOR("48 89 5C 24 ? 48 89 6C 24 ? 56 57 41 56 48 81 EC ? ? ? ? 48 8D 0D")));
|
||||
bSuccess &= (fnCreateMaterial != nullptr);
|
||||
L_PRINT(LOG_INFO) << CS_XOR("[Memory] Loaded fnCreateMaterial");
|
||||
|
||||
load_key_value = reinterpret_cast<decltype(load_key_value)>(GetExportAddress(hTier0, CS_XOR("?LoadKV3@@YA_NPEAVKeyValues3@@PEAVCUtlString@@PEBDAEBUKV3ID_t@@2@Z")));
|
||||
bSuccess &= (load_key_value != nullptr);
|
||||
L_PRINT(LOG_INFO) << CS_XOR("[Memory] Loaded load_key_value");
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
#pragma region memory_allocation
|
||||
|
||||
/*
|
||||
* overload global new/delete operators with our allocators
|
||||
* - @note: ensure that all sdk classes that can be instantiated have an overloaded constructor and/or game allocator, otherwise marked as non-constructible
|
||||
*/
|
||||
void* __cdecl operator new(const std::size_t nSize)
|
||||
{
|
||||
return MEM::HeapAlloc(nSize);
|
||||
}
|
||||
|
||||
void* __cdecl operator new[](const std::size_t nSize)
|
||||
{
|
||||
return MEM::HeapAlloc(nSize);
|
||||
}
|
||||
|
||||
void __cdecl operator delete(void* pMemory) noexcept
|
||||
{
|
||||
MEM::HeapFree(pMemory);
|
||||
}
|
||||
|
||||
void __cdecl operator delete[](void* pMemory) noexcept
|
||||
{
|
||||
MEM::HeapFree(pMemory);
|
||||
}
|
||||
|
||||
void* MEM::HeapAlloc(const std::size_t nSize)
|
||||
{
|
||||
const HANDLE hHeap = ::GetProcessHeap();
|
||||
return ::HeapAlloc(hHeap, 0UL, nSize);
|
||||
}
|
||||
|
||||
void MEM::HeapFree(void* pMemory)
|
||||
{
|
||||
if (pMemory != nullptr)
|
||||
{
|
||||
const HANDLE hHeap = ::GetProcessHeap();
|
||||
::HeapFree(hHeap, 0UL, pMemory);
|
||||
}
|
||||
}
|
||||
|
||||
void* MEM::HeapRealloc(void* pMemory, const std::size_t nNewSize)
|
||||
{
|
||||
if (pMemory == nullptr)
|
||||
return HeapAlloc(nNewSize);
|
||||
|
||||
if (nNewSize == 0UL)
|
||||
{
|
||||
HeapFree(pMemory);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const HANDLE hHeap = ::GetProcessHeap();
|
||||
return ::HeapReAlloc(hHeap, 0UL, pMemory, nNewSize);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// @todo: move to win.cpp (or platform.cpp?) except getsectioninfo
|
||||
#pragma region memory_get
|
||||
|
||||
void* MEM::GetModuleBaseHandle(const wchar_t* wszModuleName)
|
||||
{
|
||||
const _PEB* pPEB = reinterpret_cast<_PEB*>(__readgsqword(0x60));
|
||||
|
||||
if (wszModuleName == nullptr)
|
||||
return pPEB->ImageBaseAddress;
|
||||
|
||||
void* pModuleBase = nullptr;
|
||||
for (LIST_ENTRY* pListEntry = pPEB->Ldr->InMemoryOrderModuleList.Flink; pListEntry != &pPEB->Ldr->InMemoryOrderModuleList; pListEntry = pListEntry->Flink)
|
||||
{
|
||||
const _LDR_DATA_TABLE_ENTRY* pEntry = CONTAINING_RECORD(pListEntry, _LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
|
||||
|
||||
if (pEntry->FullDllName.Buffer != nullptr && CRT::StringCompare(wszModuleName, pEntry->BaseDllName.Buffer) == 0)
|
||||
{
|
||||
pModuleBase = pEntry->DllBase;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pModuleBase == nullptr)
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("module base not found: \"") << wszModuleName << CS_XOR("\"");
|
||||
|
||||
return pModuleBase;
|
||||
}
|
||||
|
||||
const wchar_t* MEM::GetModuleBaseFileName(const void* hModuleBase)
|
||||
{
|
||||
const _PEB* pPEB = reinterpret_cast<_PEB*>(__readgsqword(0x60));
|
||||
|
||||
if (hModuleBase == nullptr)
|
||||
hModuleBase = pPEB->ImageBaseAddress;
|
||||
|
||||
::EnterCriticalSection(pPEB->LoaderLock);
|
||||
|
||||
const wchar_t* wszModuleName = nullptr;
|
||||
for (LIST_ENTRY* pListEntry = pPEB->Ldr->InMemoryOrderModuleList.Flink; pListEntry != &pPEB->Ldr->InMemoryOrderModuleList; pListEntry = pListEntry->Flink)
|
||||
{
|
||||
const _LDR_DATA_TABLE_ENTRY* pEntry = CONTAINING_RECORD(pListEntry, _LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
|
||||
|
||||
if (pEntry->DllBase == hModuleBase)
|
||||
{
|
||||
wszModuleName = pEntry->BaseDllName.Buffer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
::LeaveCriticalSection(pPEB->LoaderLock);
|
||||
|
||||
return wszModuleName;
|
||||
}
|
||||
|
||||
void* MEM::GetExportAddress(const void* hModuleBase, const char* szProcedureName)
|
||||
{
|
||||
const auto pBaseAddress = static_cast<const std::uint8_t*>(hModuleBase);
|
||||
|
||||
const auto pIDH = static_cast<const IMAGE_DOS_HEADER*>(hModuleBase);
|
||||
if (pIDH->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return nullptr;
|
||||
|
||||
const auto pINH = reinterpret_cast<const IMAGE_NT_HEADERS64*>(pBaseAddress + pIDH->e_lfanew);
|
||||
if (pINH->Signature != IMAGE_NT_SIGNATURE)
|
||||
return nullptr;
|
||||
|
||||
const IMAGE_OPTIONAL_HEADER64* pIOH = &pINH->OptionalHeader;
|
||||
const std::uintptr_t nExportDirectorySize = pIOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
||||
const std::uintptr_t uExportDirectoryAddress = pIOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
|
||||
if (nExportDirectorySize == 0U || uExportDirectoryAddress == 0U)
|
||||
{
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("module has no exports: \"") << GetModuleBaseFileName(hModuleBase) << CS_XOR("\"");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto pIED = reinterpret_cast<const IMAGE_EXPORT_DIRECTORY*>(pBaseAddress + uExportDirectoryAddress);
|
||||
const auto pNamesRVA = reinterpret_cast<const std::uint32_t*>(pBaseAddress + pIED->AddressOfNames);
|
||||
const auto pNameOrdinalsRVA = reinterpret_cast<const std::uint16_t*>(pBaseAddress + pIED->AddressOfNameOrdinals);
|
||||
const auto pFunctionsRVA = reinterpret_cast<const std::uint32_t*>(pBaseAddress + pIED->AddressOfFunctions);
|
||||
|
||||
// Perform binary search to find the export by name
|
||||
std::size_t nRight = pIED->NumberOfNames, nLeft = 0U;
|
||||
while (nRight != nLeft)
|
||||
{
|
||||
// Avoid INT_MAX/2 overflow
|
||||
const std::size_t uMiddle = nLeft + ((nRight - nLeft) >> 1U);
|
||||
const int iResult = CRT::StringCompare(szProcedureName, reinterpret_cast<const char*>(pBaseAddress + pNamesRVA[uMiddle]));
|
||||
|
||||
if (iResult == 0)
|
||||
{
|
||||
const std::uint32_t uFunctionRVA = pFunctionsRVA[pNameOrdinalsRVA[uMiddle]];
|
||||
|
||||
#ifdef _DEBUG
|
||||
L_PRINT(LOG_INFO) << CS_XOR("export found: \"") << reinterpret_cast<const char*>(pBaseAddress + pNamesRVA[uMiddle]) << CS_XOR("\" in \"") << GetModuleBaseFileName(hModuleBase) << CS_XOR("\" at: ") << L::AddFlags(LOG_MODE_INT_SHOWBASE | LOG_MODE_INT_FORMAT_HEX) << uFunctionRVA;
|
||||
#else
|
||||
L_PRINT(LOG_INFO) << CS_XOR("export found: ") << szProcedureName;
|
||||
#endif // _DEBUG
|
||||
|
||||
// Check if it's a forwarded export
|
||||
if (uFunctionRVA >= uExportDirectoryAddress && uFunctionRVA - uExportDirectoryAddress < nExportDirectorySize)
|
||||
{
|
||||
// Forwarded exports are not supported
|
||||
break;
|
||||
}
|
||||
|
||||
return const_cast<std::uint8_t*>(pBaseAddress) + uFunctionRVA;
|
||||
}
|
||||
|
||||
if (iResult > 0)
|
||||
nLeft = uMiddle + 1;
|
||||
else
|
||||
nRight = uMiddle;
|
||||
}
|
||||
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("export not found: ") << szProcedureName;
|
||||
|
||||
// Export not found
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool MEM::GetSectionInfo(const void* hModuleBase, const char* szSectionName, std::uint8_t** ppSectionStart, std::size_t* pnSectionSize)
|
||||
{
|
||||
const auto pBaseAddress = static_cast<const std::uint8_t*>(hModuleBase);
|
||||
|
||||
const auto pIDH = static_cast<const IMAGE_DOS_HEADER*>(hModuleBase);
|
||||
if (pIDH->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return false;
|
||||
|
||||
const auto pINH = reinterpret_cast<const IMAGE_NT_HEADERS*>(pBaseAddress + pIDH->e_lfanew);
|
||||
if (pINH->Signature != IMAGE_NT_SIGNATURE)
|
||||
return false;
|
||||
|
||||
const IMAGE_SECTION_HEADER* pISH = IMAGE_FIRST_SECTION(pINH);
|
||||
|
||||
// go through all code sections
|
||||
for (WORD i = 0U; i < pINH->FileHeader.NumberOfSections; i++, pISH++)
|
||||
{
|
||||
// @test: use case insensitive comparison instead?
|
||||
if (CRT::StringCompareN(szSectionName, reinterpret_cast<const char*>(pISH->Name), IMAGE_SIZEOF_SHORT_NAME) == 0)
|
||||
{
|
||||
if (ppSectionStart != nullptr)
|
||||
*ppSectionStart = const_cast<std::uint8_t*>(pBaseAddress) + pISH->VirtualAddress;
|
||||
|
||||
if (pnSectionSize != nullptr)
|
||||
*pnSectionSize = pISH->SizeOfRawData;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("code section not found: \"") << szSectionName << CS_XOR("\"");
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region memory_search
|
||||
UTILPtr MEM::FindPatterns(const wchar_t* wszModuleName, const char* szPattern)
|
||||
{
|
||||
// convert pattern string to byte array
|
||||
const std::size_t nApproximateBufferSize = (CRT::StringLength(szPattern) >> 1U) + 1U;
|
||||
std::uint8_t* arrByteBuffer = static_cast<std::uint8_t*>(MEM_STACKALLOC(nApproximateBufferSize));
|
||||
char* szMaskBuffer = static_cast<char*>(MEM_STACKALLOC(nApproximateBufferSize));
|
||||
PatternToBytes(szPattern, arrByteBuffer, szMaskBuffer);
|
||||
|
||||
// @test: use search with straight in-place conversion? do not think it will be faster, cuz of bunch of new checks that gonna be performed for each iteration
|
||||
return FindPattern(wszModuleName, reinterpret_cast<const char*>(arrByteBuffer), szMaskBuffer);
|
||||
}
|
||||
std::uint8_t* MEM::FindPattern(const wchar_t* wszModuleName, const char* szPattern)
|
||||
{
|
||||
// convert pattern string to byte array
|
||||
const std::size_t nApproximateBufferSize = (CRT::StringLength(szPattern) >> 1U) + 1U;
|
||||
std::uint8_t* arrByteBuffer = static_cast<std::uint8_t*>(MEM_STACKALLOC(nApproximateBufferSize));
|
||||
char* szMaskBuffer = static_cast<char*>(MEM_STACKALLOC(nApproximateBufferSize));
|
||||
PatternToBytes(szPattern, arrByteBuffer, szMaskBuffer);
|
||||
|
||||
// @test: use search with straight in-place conversion? do not think it will be faster, cuz of bunch of new checks that gonna be performed for each iteration
|
||||
return FindPattern(wszModuleName, reinterpret_cast<const char*>(arrByteBuffer), szMaskBuffer);
|
||||
}
|
||||
std::uint8_t* MEM::FindPattern(const wchar_t* wszModuleName, const char* szBytePattern, const char* szByteMask)
|
||||
{
|
||||
const void* hModuleBase = spoof_call<void*>(_fake_addr, &GetModuleBaseHandle, wszModuleName);
|
||||
|
||||
if (hModuleBase == nullptr)
|
||||
{
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("failed to get module handle for: \"") << wszModuleName << CS_XOR("\"");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto pBaseAddress = static_cast<const std::uint8_t*>(hModuleBase);
|
||||
|
||||
const auto pIDH = static_cast<const IMAGE_DOS_HEADER*>(hModuleBase);
|
||||
if (pIDH->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("failed to get module size, image is invalid");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto pINH = reinterpret_cast<const IMAGE_NT_HEADERS*>(pBaseAddress + pIDH->e_lfanew);
|
||||
if (pINH->Signature != IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("failed to get module size, image is invalid");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::uint8_t* arrByteBuffer = reinterpret_cast<const std::uint8_t*>(szBytePattern);
|
||||
const std::size_t nByteCount = CRT::StringLength(szByteMask);
|
||||
|
||||
std::uint8_t* pFoundAddress = nullptr;
|
||||
|
||||
// perform little overhead to keep all patterns unique
|
||||
#ifdef CS_PARANOID_PATTERN_UNIQUENESS
|
||||
const std::vector<std::uint8_t*> vecFoundOccurrences = FindPatternAllOccurrencesEx(pBaseAddress, pINH->OptionalHeader.SizeOfImage, arrByteBuffer, nByteCount, szByteMask);
|
||||
|
||||
// notify user about non-unique pattern
|
||||
if (!vecFoundOccurrences.empty())
|
||||
{
|
||||
// notify user about non-unique pattern
|
||||
if (vecFoundOccurrences.size() > 1U)
|
||||
{
|
||||
char* szPattern = static_cast<char*>(MEM_STACKALLOC((nByteCount << 1U) + nByteCount));
|
||||
[[maybe_unused]] const std::size_t nConvertedPatternLength = BytesToPattern(arrByteBuffer, nByteCount, szPattern);
|
||||
|
||||
L_PRINT(LOG_WARNING) << CS_XOR("found more than one occurrence with \"") << szPattern << CS_XOR("\" pattern, consider updating it!");
|
||||
|
||||
MEM_STACKFREE(szPattern);
|
||||
}
|
||||
|
||||
// return first found occurrence
|
||||
pFoundAddress = vecFoundOccurrences[0];
|
||||
}
|
||||
#else
|
||||
// @todo: we also can go through code sections and skip noexec pages, but will it really improve performance? / or at least for all occurrences search
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_section_header
|
||||
#if 0
|
||||
IMAGE_SECTION_HEADER* pCurrentSection = IMAGE_FIRST_SECTION(pINH);
|
||||
for (WORD i = 0U; i != pINH->FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
// check does page have executable code
|
||||
if (pCurrentSection->Characteristics & IMAGE_SCN_CNT_CODE || pCurrentSection->Characteristics & IMAGE_SCN_MEM_EXECUTE)
|
||||
{
|
||||
pFoundAddress = FindPatternEx(pBaseAddress + pCurrentSection->VirtualAddress, pCurrentSection->SizeOfRawData, arrByteBuffer, nByteCount, szByteMask);
|
||||
|
||||
if (pFoundAddress != nullptr)
|
||||
break;
|
||||
}
|
||||
|
||||
++pCurrentSection;
|
||||
}
|
||||
#else
|
||||
pFoundAddress = FindPatternEx(pBaseAddress, pINH->OptionalHeader.SizeOfImage, arrByteBuffer, nByteCount, szByteMask);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (pFoundAddress == nullptr)
|
||||
{
|
||||
char* szPattern = static_cast<char*>(MEM_STACKALLOC((nByteCount << 1U) + nByteCount));
|
||||
[[maybe_unused]] const std::size_t nConvertedPatternLength = BytesToPattern(arrByteBuffer, nByteCount, szPattern);
|
||||
|
||||
L_PRINT(LOG_ERROR) << CS_XOR("pattern not found: \"") << szPattern << CS_XOR("\"");
|
||||
|
||||
MEM_STACKFREE(szPattern);
|
||||
}
|
||||
|
||||
return pFoundAddress;
|
||||
}
|
||||
|
||||
// @todo: msvc poorly optimizes this, it looks even better w/o optimization at all
|
||||
std::uint8_t* MEM::FindPatternEx(const std::uint8_t* pRegionStart, const std::size_t nRegionSize, const std::uint8_t* arrByteBuffer, const std::size_t nByteCount, const char* szByteMask)
|
||||
{
|
||||
std::uint8_t* pCurrentAddress = const_cast<std::uint8_t*>(pRegionStart);
|
||||
const std::uint8_t* pRegionEnd = pRegionStart + nRegionSize - nByteCount;
|
||||
const bool bIsMaskUsed = (szByteMask != nullptr);
|
||||
|
||||
while (pCurrentAddress < pRegionEnd)
|
||||
{
|
||||
// check the first byte before entering the loop, otherwise if there two consecutive bytes of first byte in the buffer, we may skip both and fail the search
|
||||
if ((bIsMaskUsed && *szByteMask == '?') || *pCurrentAddress == *arrByteBuffer)
|
||||
{
|
||||
if (nByteCount == 1)
|
||||
return pCurrentAddress;
|
||||
|
||||
// compare the least byte sequence and continue on wildcard or skip forward on first mismatched byte
|
||||
std::size_t nComparedBytes = 0U;
|
||||
while ((bIsMaskUsed && szByteMask[nComparedBytes + 1U] == '?') || pCurrentAddress[nComparedBytes + 1U] == arrByteBuffer[nComparedBytes + 1U])
|
||||
{
|
||||
// check does byte sequence match
|
||||
if (++nComparedBytes == nByteCount - 1U)
|
||||
return pCurrentAddress;
|
||||
}
|
||||
|
||||
// skip non suitable bytes
|
||||
pCurrentAddress += nComparedBytes;
|
||||
}
|
||||
|
||||
++pCurrentAddress;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t*> MEM::FindPatternAllOccurrencesEx(const std::uint8_t* pRegionStart, const std::size_t nRegionSize, const std::uint8_t* arrByteBuffer, const std::size_t nByteCount, const char* szByteMask)
|
||||
{
|
||||
const std::uint8_t* pRegionEnd = pRegionStart + nRegionSize - nByteCount;
|
||||
const bool bIsMaskUsed = (szByteMask != nullptr);
|
||||
|
||||
// container for addresses of the all found occurrences
|
||||
std::vector<std::uint8_t*> vecOccurrences = {};
|
||||
|
||||
for (std::uint8_t* pCurrentByte = const_cast<std::uint8_t*>(pRegionStart); pCurrentByte < pRegionEnd; ++pCurrentByte)
|
||||
{
|
||||
// do a first byte check before entering the loop, otherwise if there two consecutive bytes of first byte in the buffer, we may skip both and fail the search
|
||||
if ((!bIsMaskUsed || *szByteMask != '?') && *pCurrentByte != *arrByteBuffer)
|
||||
continue;
|
||||
|
||||
// check for bytes sequence match
|
||||
bool bSequenceMatch = true;
|
||||
for (std::size_t i = 1U; i < nByteCount; i++)
|
||||
{
|
||||
// compare sequence and continue on wildcard or skip forward on first mismatched byte
|
||||
if ((!bIsMaskUsed || szByteMask[i] != '?') && pCurrentByte[i] != arrByteBuffer[i])
|
||||
{
|
||||
// skip non suitable bytes
|
||||
pCurrentByte += i - 1U;
|
||||
|
||||
bSequenceMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check did we found address
|
||||
if (bSequenceMatch)
|
||||
vecOccurrences.push_back(pCurrentByte);
|
||||
}
|
||||
|
||||
return vecOccurrences;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region memory_extra
|
||||
|
||||
std::size_t MEM::PatternToBytes(const char* szPattern, std::uint8_t* pOutByteBuffer, char* szOutMaskBuffer)
|
||||
{
|
||||
std::uint8_t* pCurrentByte = pOutByteBuffer;
|
||||
|
||||
while (*szPattern != '\0')
|
||||
{
|
||||
// check is a wildcard
|
||||
if (*szPattern == '?')
|
||||
{
|
||||
++szPattern;
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(*szPattern == '\0' || *szPattern == ' ' || *szPattern == '?'); // we're expect that next character either terminating null, whitespace or part of double wildcard (note that it's required if your pattern written without whitespaces)
|
||||
#endif
|
||||
|
||||
// ignore that
|
||||
*pCurrentByte++ = 0U;
|
||||
*szOutMaskBuffer++ = '?';
|
||||
}
|
||||
// check is not space
|
||||
else if (*szPattern != ' ')
|
||||
{
|
||||
// convert two consistent numbers in a row to byte value
|
||||
std::uint8_t uByte = static_cast<std::uint8_t>(CRT::CharToHexInt(*szPattern) << 4);
|
||||
|
||||
++szPattern;
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(*szPattern != '\0' && *szPattern != '?' && *szPattern != ' '); // we're expect that byte always represented by two numbers in a row
|
||||
#endif
|
||||
|
||||
uByte |= static_cast<std::uint8_t>(CRT::CharToHexInt(*szPattern));
|
||||
|
||||
*pCurrentByte++ = uByte;
|
||||
*szOutMaskBuffer++ = 'x';
|
||||
}
|
||||
|
||||
++szPattern;
|
||||
}
|
||||
|
||||
// zero terminate both buffers
|
||||
*pCurrentByte = 0U;
|
||||
*szOutMaskBuffer = '\0';
|
||||
|
||||
return pCurrentByte - pOutByteBuffer;
|
||||
}
|
||||
|
||||
std::size_t MEM::BytesToPattern(const std::uint8_t* pByteBuffer, const std::size_t nByteCount, char* szOutBuffer)
|
||||
{
|
||||
char* szCurrentPattern = szOutBuffer;
|
||||
|
||||
for (std::size_t i = 0U; i < nByteCount; i++)
|
||||
{
|
||||
// manually convert byte to chars
|
||||
const char* szHexByte = &CRT::_TWO_DIGITS_HEX_LUT[pByteBuffer[i] * 2U];
|
||||
*szCurrentPattern++ = szHexByte[0];
|
||||
*szCurrentPattern++ = szHexByte[1];
|
||||
*szCurrentPattern++ = ' ';
|
||||
}
|
||||
*--szCurrentPattern = '\0';
|
||||
|
||||
return szCurrentPattern - szOutBuffer;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
@@ -0,0 +1,199 @@
|
||||
#pragma once
|
||||
// used: memory api
|
||||
#include <memory>
|
||||
// used: std::vector
|
||||
#include <vector>
|
||||
#include <span>
|
||||
#include "../common.h"
|
||||
#include "../sdk/datatypes/K3V.h"
|
||||
#include "../utilities/log.h"
|
||||
#pragma region memory_definitions
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 6255) // '_alloca' indicates failure by raising a stack overflow exception. consider using '_malloca' instead
|
||||
#define MEM_STACKALLOC(SIZE) _malloca(SIZE)
|
||||
#pragma warning(pop)
|
||||
#define MEM_STACKFREE(MEMORY) static_cast<void>(0)
|
||||
|
||||
#define MEM_PAD(SIZE) \
|
||||
private: \
|
||||
char CS_CONCATENATE(pad_0, __COUNTER__)[SIZE]; \
|
||||
public:
|
||||
#pragma endregion
|
||||
|
||||
|
||||
// Pointer arithmetic utility class.
|
||||
struct UTILPtr {
|
||||
public:
|
||||
template <typename T>
|
||||
UTILPtr(T val) {
|
||||
m_val = (uintptr_t)(val);
|
||||
}
|
||||
|
||||
template <typename T = void*>
|
||||
T Get(const char* variableName = nullptr) {
|
||||
#ifdef CS2_SDK_ENABLE_LOGGING
|
||||
if (variableName) LOG("%s found at -> %llX\n", variableName, m_val);
|
||||
#endif
|
||||
|
||||
return (T)(m_val);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Get(T& dst, const char* variableName = nullptr) {
|
||||
dst = Get<T>(variableName);
|
||||
}
|
||||
|
||||
UTILPtr& AddOffset(int offset) {
|
||||
if (m_val) m_val += offset;
|
||||
return *this;
|
||||
}
|
||||
UTILPtr& ToAbsolute(int preOffset, int postOffset) {
|
||||
if (m_val) {
|
||||
AddOffset(preOffset);
|
||||
m_val = m_val + sizeof(int) + *(int*)(m_val);
|
||||
AddOffset(postOffset);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
UTILPtr& Dereference(int dereferences) {
|
||||
if (m_val)
|
||||
while (dereferences-- != 0) m_val = *(uintptr_t*)(m_val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IsValid() { return m_val != 0; }
|
||||
|
||||
private:
|
||||
uintptr_t m_val;
|
||||
};
|
||||
|
||||
namespace MEM
|
||||
{
|
||||
bool Setup();
|
||||
|
||||
/* @section: allocation */
|
||||
// allocate a block of memory from a heap
|
||||
[[nodiscard]] void* HeapAlloc(const std::size_t nSize);
|
||||
// free a memory block allocated from a heap
|
||||
void HeapFree(void* pMemory);
|
||||
// reallocate a block of memory from a heap
|
||||
// @note: we're expect this to allocate instead when passed null, and free if size is null
|
||||
void* HeapRealloc(void* pMemory, const std::size_t nNewSize);
|
||||
|
||||
/* @section: get */
|
||||
/// alternative of 'GetModuleHandle()'
|
||||
/// @param[in] wszModuleName module name to search base handle for, null means current process
|
||||
/// @returns: base handle of module with given name if it exist, null otherwise
|
||||
[[nodiscard]] void* GetModuleBaseHandle(const wchar_t* wszModuleName);
|
||||
/// alternative of 'GetModuleFileName()'
|
||||
/// @param[in] hModuleBase module base to search filename for, null means current process
|
||||
/// @returns: name of given module if it's valid, null otherwise
|
||||
[[nodiscard]] const wchar_t* GetModuleBaseFileName(const void* hModuleBase);
|
||||
/// alternative of 'GetProcAddress()'
|
||||
/// @remarks: doesn't support forwarded exports, this means you may need to manual call 'LoadLibrary'/'FreeLibrary' for export library
|
||||
/// @returns: pointer to exported procedure
|
||||
[[nodiscard]] void* GetExportAddress(const void* hModuleBase, const char* szProcedureName);
|
||||
|
||||
/// @param[in] szSectionName section to get info of (e.g. ".rdata", ".text", etc)
|
||||
/// @param[out] ppSectionStart output for section start address
|
||||
/// @param[out] pnSectionSize output for section size
|
||||
/// @returns: true if code section has been found, false otherwise
|
||||
[[nodiscard]] bool GetSectionInfo(const void* hModuleBase, const char* szSectionName, std::uint8_t** ppSectionStart, std::size_t* pnSectionSize);
|
||||
/// get absolute address from relative address
|
||||
/// @param[in] pRelativeAddress pointer to relative address, e.g. destination address from JMP, JE, JNE and others instructions
|
||||
/// @param[in] nPreOffset offset before relative address
|
||||
/// @param[in] nPostOffset offset after relative address
|
||||
/// @returns: pointer to absolute address
|
||||
template <typename T = std::uint8_t>
|
||||
[[nodiscard]] T* GetAbsoluteAddress(T* pRelativeAddress, int nPreOffset = 0x0, int nPostOffset = 0x0)
|
||||
{
|
||||
pRelativeAddress += nPreOffset;
|
||||
pRelativeAddress += sizeof(std::int32_t) + *reinterpret_cast<std::int32_t*>(pRelativeAddress);
|
||||
pRelativeAddress += nPostOffset;
|
||||
return pRelativeAddress;
|
||||
}
|
||||
/// resolve rip relative address
|
||||
/// @param[in] nAddressBytes as byte for the address we want to resolve
|
||||
/// @param[in] nRVAOffset offset of the relative address
|
||||
/// @param[in] nRIPOffset offset of the instruction pointer
|
||||
/// @returns: pointer to resolved address
|
||||
[[nodiscard]] CS_INLINE std::uint8_t* ResolveRelativeAddress(std::uint8_t* nAddressBytes, std::uint32_t nRVAOffset, std::uint32_t nRIPOffset)
|
||||
{
|
||||
std::uint32_t nRVA = *reinterpret_cast<std::uint32_t*>(nAddressBytes + nRVAOffset);
|
||||
std::uint64_t nRIP = reinterpret_cast<std::uint64_t>(nAddressBytes) + nRIPOffset;
|
||||
|
||||
return reinterpret_cast<std::uint8_t*>(nRVA + nRIP);
|
||||
}
|
||||
|
||||
/// get pointer to function of virtual-function table
|
||||
/// @returns: pointer to virtual function
|
||||
template <typename T = void*>
|
||||
[[nodiscard]] CS_INLINE T GetVFunc(const void* thisptr, std::size_t nIndex)
|
||||
{
|
||||
return (*static_cast<T* const*>(thisptr))[nIndex];
|
||||
}
|
||||
/// call virtual function of specified class at given index
|
||||
/// @note: reference and const reference arguments must be forwarded as pointers or wrapped with 'std::ref'/'std::cref' calls!
|
||||
/// @returns: result of virtual function call
|
||||
template <typename T, std::size_t nIndex, class CBaseClass, typename... Args_t>
|
||||
static CS_INLINE T CallVFunc(CBaseClass* thisptr, Args_t... argList)
|
||||
{
|
||||
using VirtualFn_t = T(__thiscall*)(const void*, decltype(argList)...);
|
||||
return (*reinterpret_cast<VirtualFn_t* const*>(reinterpret_cast<std::uintptr_t>(thisptr)))[nIndex](thisptr, argList...);
|
||||
}
|
||||
[[nodiscard]] uintptr_t FindPattern(const std::span<const int>& pattern) ;
|
||||
/* @section: search */
|
||||
/// ida style pattern byte comparison in a specific mo dule
|
||||
/// @param[in] wszModuleName module name where to search for pattern
|
||||
/// @param[in] szPattern ida style pattern, e.g. "55 8B 40 ? 30", wildcard can be either '?' or "??", bytes always presented by two numbers in a row [00 .. FF], whitespaces can be omitted (wildcards in this case should be two-character)
|
||||
/// @returns: pointer to address of the first found occurrence with equal byte sequence on success, null otherwise
|
||||
[[nodiscard]] std::uint8_t* FindPattern(const wchar_t* wszModuleName, const char* szPattern);
|
||||
[[nodiscard]] UTILPtr FindPatterns(const wchar_t* wszModuleName, const char* szPattern);
|
||||
|
||||
/// naive style pattern byte comparison in a specific module
|
||||
/// @param[in] wszModuleName module name where to search for pattern
|
||||
/// @param[in] szBytePattern naive style pattern, e.g. "\x55\x8B\x40\x00\x30", wildcard bytes value ignored
|
||||
/// @param[in] szByteMask wildcard mask for byte array, e.g. "xxx?x", should always correspond to bytes count
|
||||
/// @returns: pointer to address of the first found occurrence with equal byte sequence on success, null otherwise
|
||||
[[nodiscard]] std::uint8_t* FindPattern(const wchar_t* wszModuleName, const char* szBytePattern, const char* szByteMask);
|
||||
/// pattern byte comparison in the specific region
|
||||
/// @param[in] arrByteBuffer byte sequence to search
|
||||
/// @param[in] nByteCount count of search bytes
|
||||
/// @param[in] szByteMask [optional] wildcard mask for byte array
|
||||
/// @returns: pointer to address of the first found occurrence with equal byte sequence on success, null otherwise
|
||||
[[nodiscard]] std::uint8_t* FindPatternEx(const std::uint8_t* pRegionStart, const std::size_t nRegionSize, const std::uint8_t* arrByteBuffer, const std::size_t nByteCount, const char* szByteMask = nullptr);
|
||||
/// pattern byte comparison in the specific region
|
||||
/// @param[in] arrByteBuffer byte sequence to search
|
||||
/// @param[in] nByteCount count of search bytes
|
||||
/// @param[in] szByteMask [optional] wildcard mask for byte array
|
||||
/// @returns: pointers to addresses of the all found occurrences with equal byte sequence on success, empty otherwise
|
||||
[[nodiscard]] std::vector<std::uint8_t*> FindPatternAllOccurrencesEx(const std::uint8_t* pRegionStart, const std::size_t nRegionSize, const std::uint8_t* arrByteBuffer, const std::size_t nByteCount, const char* szByteMask = nullptr);
|
||||
/// class RTTI virtual table search in a specific module
|
||||
/// @returns: pointer to the found virtual table on success, null otherwise
|
||||
|
||||
/* @section: extra */
|
||||
/// convert ida-style pattern to byte array
|
||||
/// @param[in] szPattern ida-style pattern, e.g. "55 8B 40 ? 30", wildcard can be either '?' or "??", bytes are always presented by two numbers in a row [00 .. FF], blank delimiters are ignored and not necessary (wildcard in this case should be two-character)
|
||||
/// @param[out] pOutByteBuffer output for converted, zero-terminated byte array
|
||||
/// @param[out] szOutMaskBuffer output for wildcard, zero-terminated byte mask
|
||||
/// @returns: count of the converted bytes from the pattern
|
||||
std::size_t PatternToBytes(const char* szPattern, std::uint8_t* pOutByteBuffer, char* szOutMaskBuffer);
|
||||
/// convert byte array to ida-style pattern
|
||||
/// @param[in] pByteBuffer buffer of bytes to convert
|
||||
/// @param[in] nByteCount count of bytes to convert
|
||||
/// @param[out] szOutBuffer output for converted pattern
|
||||
/// @returns: length of the converted ida-style pattern, not including the terminating null
|
||||
std::size_t BytesToPattern(const std::uint8_t* pByteBuffer, const std::size_t nByteCount, char* szOutBuffer);
|
||||
|
||||
/* @section: game exports */
|
||||
inline unsigned long(CS_STDCALL* fnUnDecorateSymbolName)(const char* szName, char* pszOutput, unsigned long nMaxStringLength, unsigned long dwFlags) = nullptr;
|
||||
|
||||
// SDL window stuffs
|
||||
// @note: helpful for doing our mouse cursor like force show it when our menu is opened
|
||||
inline int(CS_STDCALL* fnSetRelativeMouseMode)(int) = nullptr;
|
||||
inline int(CS_STDCALL* fnSetWindowGrab)(void*, int) = nullptr;
|
||||
inline int(CS_STDCALL* fnWarpMouseInWindow)(void*, float, float) = nullptr;
|
||||
inline bool(__fastcall* load_key_value)(CKeyValues3*, void*, const char*, const KV3IVD_t*, const char*);
|
||||
|
||||
inline std::int64_t(__fastcall* fnCreateMaterial)(void*, void*, const char*, void*, unsigned int, unsigned int);
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
#include "notify.h"
|
||||
|
||||
// used: cheat variables
|
||||
#include "../core/variables.h"
|
||||
// used: menu::bMainWindowOpened
|
||||
#include "../core/menu.h"
|
||||
// used: [resources] font awesome icons definitions
|
||||
#include "../../resources/font_awesome_5.h"
|
||||
// used: easingg library
|
||||
#include "easing.h"
|
||||
|
||||
inline static const float GetTime() noexcept
|
||||
{
|
||||
return static_cast<float>(clock() / 1000.f);
|
||||
}
|
||||
|
||||
inline static bool IsEmptyOrNullptr(const char* szText)
|
||||
{
|
||||
return szText == nullptr || szText[0] == '\0';
|
||||
}
|
||||
|
||||
NOTIFY::NotificationData_t::NotificationData_t(ENotificationType nType, const char* szFormat, ...) :
|
||||
nType(nType), flCreateionTime(GetTime()), animHandler(&EASING::InQuad, &EASING::OutQuad)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, szFormat);
|
||||
stbsp_vsnprintf(this->szBuffer, sizeof(szBuffer), szFormat, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
const Color_t& NOTIFY::NotificationData_t::GetTypeColor() const
|
||||
{
|
||||
switch (nType)
|
||||
{
|
||||
case N_TYPE_INFO:
|
||||
// cyan
|
||||
return Color_t(0, 255, 255);
|
||||
case N_TYPE_SUCCESS:
|
||||
// green
|
||||
return Color_t(0, 255, 0);
|
||||
case N_TYPE_WARNING:
|
||||
// yellow
|
||||
return Color_t(255, 255, 0);
|
||||
case N_TYPE_ERROR:
|
||||
// red
|
||||
return Color_t(255, 0, 0);
|
||||
default:
|
||||
// white
|
||||
return Color_t(255, 255, 255);
|
||||
}
|
||||
}
|
||||
|
||||
const char* NOTIFY::NotificationData_t::Data() const
|
||||
{
|
||||
return this->szBuffer;
|
||||
}
|
||||
|
||||
const char* NOTIFY::NotificationData_t::GetIcon() const
|
||||
{
|
||||
switch (nType)
|
||||
{
|
||||
case N_TYPE_INFO:
|
||||
return ICON_FA_INFO;
|
||||
case N_TYPE_SUCCESS:
|
||||
return ICON_FA_CHECK;
|
||||
case N_TYPE_WARNING:
|
||||
return ICON_FA_EXCLAMATION;
|
||||
case N_TYPE_ERROR:
|
||||
return ICON_FA_TIMES;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const float NOTIFY::NotificationData_t::GetTimeDelta(const float flCurrentTime) const
|
||||
{
|
||||
return flCurrentTime - this->flCreateionTime;
|
||||
}
|
||||
|
||||
void NOTIFY::Push(const NotificationData_t& notification)
|
||||
{
|
||||
vecNotifications.push_back(notification);
|
||||
}
|
||||
|
||||
void NOTIFY::_Remove(size_t nIndex)
|
||||
{
|
||||
vecNotifications.erase(vecNotifications.begin() + nIndex);
|
||||
}
|
||||
|
||||
void NOTIFY::Render()
|
||||
{
|
||||
if (vecNotifications.empty())
|
||||
return;
|
||||
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// padding with menu watermark
|
||||
float flPaddingY = (MENU::bMainWindowOpened && C_GET(bool, Vars.bWatermark)) ? ImGui::GetFrameHeight() : 0.f;
|
||||
|
||||
for (size_t i = 0U; i < vecNotifications.size(); i++)
|
||||
{
|
||||
NotificationData_t* pData = &vecNotifications[i];
|
||||
|
||||
// shouldn't happen, but maybe it does
|
||||
if (IsEmptyOrNullptr(pData->Data()))
|
||||
continue;
|
||||
|
||||
// handling animation
|
||||
const float flTimeDelta = pData->GetTimeDelta(GetTime());
|
||||
pData->animHandler.Update(io.DeltaTime, style.AnimationSpeed);
|
||||
|
||||
if (flTimeDelta >= (_MAX_TIME - 0.25f))
|
||||
pData->animHandler.SetSwitch(false);
|
||||
else if (flTimeDelta <= 0.25f)
|
||||
pData->animHandler.SetSwitch(true);
|
||||
|
||||
const float flAnimValue = pData->animHandler.GetValue(1.f);
|
||||
|
||||
// if animation is done, remove notification
|
||||
if (!pData->animHandler.GetSwitch())
|
||||
{
|
||||
_Remove(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
// render frame and notification
|
||||
CRT::String_t<32U> szWindowName(CS_XOR("notification##%d"), i);
|
||||
ImGui::SetNextWindowPos(ImVec2(style.WindowPadding.x * flAnimValue, flPaddingY * flAnimValue), ImGuiCond_Always);
|
||||
ImGui::Begin(szWindowName.Data(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoFocusOnAppearing);
|
||||
{
|
||||
if (const char* szIcon = pData->GetIcon(); szIcon != nullptr)
|
||||
{
|
||||
ImGui::TextColored(pData->GetTypeColor().GetVec4(flAnimValue), szIcon);
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
ImGui::TextColored(C_GET(ColorPickerVar_t, Vars.colPrimtv0).colValue.GetVec4(flAnimValue), pData->Data());
|
||||
|
||||
flPaddingY += ImGui::GetWindowHeight();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
// used: [stl] vector
|
||||
#include <vector>
|
||||
// used: draw wrapper
|
||||
#include "draw.h"
|
||||
|
||||
#pragma region notify_definitions
|
||||
#define NOFITY_TEXT_SIZE 64U // max size of notification text
|
||||
// @todo: use ImStyle?
|
||||
#define NOTIFY_ANIMATION_TIME 15.0 // time in ms to show/hide notification
|
||||
#define NOTIFY_DELETE_TIME 30.0 // time in ms to delete notification
|
||||
#pragma endregion
|
||||
|
||||
#pragma region notify_enumerations
|
||||
using NotificationType_t = int;
|
||||
|
||||
enum ENotificationType : NotificationType_t
|
||||
{
|
||||
N_TYPE_DEFAULT = 0,
|
||||
N_TYPE_INFO,
|
||||
N_TYPE_SUCCESS,
|
||||
N_TYPE_WARNING,
|
||||
N_TYPE_ERROR,
|
||||
N_TYPE_MAX
|
||||
};
|
||||
|
||||
using NotificationState_t = int;
|
||||
|
||||
enum ENotificationState : NotificationState_t
|
||||
{
|
||||
N_STATE_START = 0,
|
||||
N_STATE_STAY,
|
||||
N_STATE_END,
|
||||
N_STATE_EXPIRED,
|
||||
N_STATE_MAX
|
||||
};
|
||||
|
||||
#pragma endregion
|
||||
|
||||
namespace NOTIFY
|
||||
{
|
||||
struct NotificationData_t
|
||||
{
|
||||
NotificationData_t(ENotificationType nType, const char* szFormat, ...);
|
||||
|
||||
/// @return color of notification type
|
||||
const Color_t& GetTypeColor() const;
|
||||
/// @return c-type string of notification text
|
||||
const char* Data() const;
|
||||
/// @return icon of notification type
|
||||
const char* GetIcon() const;
|
||||
/// @return time difference between creation and current time
|
||||
const float GetTimeDelta(const float flCurrentTime) const;
|
||||
|
||||
int nType = 0;
|
||||
char szBuffer[NOFITY_TEXT_SIZE];
|
||||
float flCreateionTime = 0.0;
|
||||
AnimationHandler_t animHandler = AnimationHandler_t();
|
||||
};
|
||||
|
||||
/* @section: main */
|
||||
// push notification to queue
|
||||
void Push(const NotificationData_t& notification);
|
||||
// pop notification from queue
|
||||
void _Remove(size_t nIndex);
|
||||
// render notifications
|
||||
void Render();
|
||||
|
||||
/* @section: values */
|
||||
// maximum time to show notification
|
||||
inline constexpr float _MAX_TIME = 5.f;
|
||||
// maximum count of notifications
|
||||
inline std::vector<NotificationData_t> vecNotifications = {};
|
||||
}
|
||||
@@ -0,0 +1,592 @@
|
||||
#pragma once
|
||||
// used: [win] winapi
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#pragma region winapi_nt_types
|
||||
using NTSTATUS = LONG;
|
||||
using MEMORY_INFORMATION_CLASS = INT;
|
||||
#pragma endregion
|
||||
|
||||
#pragma region winapi_nt_definitions
|
||||
#define NtCurrentProcess() (reinterpret_cast<HANDLE>(-1))
|
||||
#define NtCurrentThread() (reinterpret_cast<HANDLE>(-2))
|
||||
|
||||
/*
|
||||
* NT_SUCCESS = [0x00000000 .. 0x3FFFFFFF]
|
||||
* NT_INFORMATION = [0x40000000 .. 0x7FFFFFFF]
|
||||
* NT_WARNING = [0x80000000 .. 0xBFFFFFFF]
|
||||
* NT_ERROR = [0xC0000000 .. 0xFFFFFFFF]
|
||||
*/
|
||||
#define NT_SUCCESS(STATUS) (static_cast<NTSTATUS>(STATUS) >= 0)
|
||||
#define NT_INFORMATION(STATUS) ((static_cast<ULONG>(STATUS) >> 30UL) == 1UL)
|
||||
#define NT_WARNING(STATUS) ((static_cast<ULONG>(STATUS) >> 30UL) == 2UL)
|
||||
#define NT_ERROR(STATUS) ((static_cast<ULONG>(STATUS) >> 30UL) == 3UL)
|
||||
#pragma endregion
|
||||
|
||||
#pragma region winapi_nt
|
||||
|
||||
// @credits: https://www.vergiliusproject.com/kernels/x86/Windows%2010
|
||||
|
||||
typedef struct _UNICODE_STRING
|
||||
{
|
||||
USHORT Length; // 0x0
|
||||
USHORT MaximumLength; // 0x2
|
||||
WCHAR* Buffer; // 0x8
|
||||
} UNICODE_STRING, * PUNICODE_STRING;
|
||||
|
||||
static_assert(sizeof(_UNICODE_STRING) == 0x10);
|
||||
|
||||
struct _RTL_BALANCED_NODE
|
||||
{
|
||||
union
|
||||
{
|
||||
struct _RTL_BALANCED_NODE* Children[2]; //0x0
|
||||
|
||||
struct
|
||||
{
|
||||
struct _RTL_BALANCED_NODE* Left; //0x0
|
||||
struct _RTL_BALANCED_NODE* Right; //0x8
|
||||
};
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
UCHAR Red : 1; //0x10
|
||||
UCHAR Balance : 2; //0x10
|
||||
};
|
||||
|
||||
ULONGLONG ParentValue; //0x10
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(_RTL_BALANCED_NODE) == 0x18);
|
||||
|
||||
struct _LDR_DATA_TABLE_ENTRY
|
||||
{
|
||||
struct _LIST_ENTRY InLoadOrderLinks; //0x0
|
||||
struct _LIST_ENTRY InMemoryOrderLinks; //0x10
|
||||
struct _LIST_ENTRY InInitializationOrderLinks; //0x20
|
||||
VOID* DllBase; //0x30
|
||||
VOID* EntryPoint; //0x38
|
||||
ULONG SizeOfImage; //0x40
|
||||
struct _UNICODE_STRING FullDllName; //0x48
|
||||
struct _UNICODE_STRING BaseDllName; //0x58
|
||||
|
||||
union
|
||||
{
|
||||
UCHAR FlagGroup[4]; //0x68
|
||||
ULONG Flags; //0x68
|
||||
|
||||
struct
|
||||
{
|
||||
ULONG PackagedBinary : 1; //0x68
|
||||
ULONG MarkedForRemoval : 1; //0x68
|
||||
ULONG ImageDll : 1; //0x68
|
||||
ULONG LoadNotificationsSent : 1; //0x68
|
||||
ULONG TelemetryEntryProcessed : 1; //0x68
|
||||
ULONG ProcessStaticImport : 1; //0x68
|
||||
ULONG InLegacyLists : 1; //0x68
|
||||
ULONG InIndexes : 1; //0x68
|
||||
ULONG ShimDll : 1; //0x68
|
||||
ULONG InExceptionTable : 1; //0x68
|
||||
ULONG ReservedFlags1 : 2; //0x68
|
||||
ULONG LoadInProgress : 1; //0x68
|
||||
ULONG LoadConfigProcessed : 1; //0x68
|
||||
ULONG EntryProcessed : 1; //0x68
|
||||
ULONG ProtectDelayLoad : 1; //0x68
|
||||
ULONG ReservedFlags3 : 2; //0x68
|
||||
ULONG DontCallForThreads : 1; //0x68
|
||||
ULONG ProcessAttachCalled : 1; //0x68
|
||||
ULONG ProcessAttachFailed : 1; //0x68
|
||||
ULONG CorDeferredValidate : 1; //0x68
|
||||
ULONG CorImage : 1; //0x68
|
||||
ULONG DontRelocate : 1; //0x68
|
||||
ULONG CorILOnly : 1; //0x68
|
||||
ULONG ChpeImage : 1; //0x68
|
||||
ULONG ChpeEmulatorImage : 1; //0x68
|
||||
ULONG ReservedFlags5 : 1; //0x68
|
||||
ULONG Redirected : 1; //0x68
|
||||
ULONG ReservedFlags6 : 2; //0x68
|
||||
ULONG CompatDatabaseProcessed : 1; //0x68
|
||||
};
|
||||
};
|
||||
|
||||
USHORT ObsoleteLoadCount; //0x6c
|
||||
USHORT TlsIndex; //0x6e
|
||||
struct _LIST_ENTRY HashLinks; //0x70
|
||||
ULONG TimeDateStamp; //0x80
|
||||
struct _ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88
|
||||
VOID* Lock; //0x90
|
||||
struct _LDR_DDAG_NODE* DdagNode; //0x98
|
||||
struct _LIST_ENTRY NodeModuleLink; //0xa0
|
||||
struct _LDRP_LOAD_CONTEXT* LoadContext; //0xb0
|
||||
VOID* ParentDllBase; //0xb8
|
||||
VOID* SwitchBackContext; //0xc0
|
||||
_RTL_BALANCED_NODE BaseAddressIndexNode; //0xc8
|
||||
_RTL_BALANCED_NODE MappingInfoIndexNode; //0xe0
|
||||
ULONGLONG OriginalBase; //0xf8
|
||||
union _LARGE_INTEGER LoadTime; //0x100
|
||||
ULONG BaseNameHashValue; //0x108
|
||||
enum _LDR_DLL_LOAD_REASON LoadReason; //0x10c
|
||||
ULONG ImplicitPathOptions; //0x110
|
||||
ULONG ReferenceCount; //0x114
|
||||
ULONG DependentLoadFlags; //0x118
|
||||
UCHAR SigningLevel; //0x11c
|
||||
ULONG CheckSum; //0x120
|
||||
VOID* ActivePatchImageBase; //0x128
|
||||
enum _LDR_HOT_PATCH_STATE HotPatchState; //0x130
|
||||
};
|
||||
|
||||
static_assert(sizeof(_LDR_DATA_TABLE_ENTRY) == 0x138);
|
||||
|
||||
struct _PEB_LDR_DATA
|
||||
{
|
||||
ULONG Length; //0x0
|
||||
UCHAR Initialized; //0x4
|
||||
VOID* SsHandle; //0x8
|
||||
struct _LIST_ENTRY InLoadOrderModuleList; //0x10
|
||||
struct _LIST_ENTRY InMemoryOrderModuleList; //0x20
|
||||
struct _LIST_ENTRY InInitializationOrderModuleList; //0x30
|
||||
VOID* EntryInProgress; //0x40
|
||||
UCHAR ShutdownInProgress; //0x48
|
||||
VOID* ShutdownThreadId; //0x50
|
||||
};
|
||||
|
||||
static_assert(sizeof(_PEB_LDR_DATA) == 0x58);
|
||||
|
||||
struct _CURDIR
|
||||
{
|
||||
struct _UNICODE_STRING DosPath; //0x0
|
||||
VOID* Handle; //0x10
|
||||
};
|
||||
|
||||
static_assert(sizeof(_CURDIR) == 0x18);
|
||||
|
||||
struct _STRING
|
||||
{
|
||||
USHORT Length; //0x0
|
||||
USHORT MaximumLength; //0x2
|
||||
CHAR* Buffer; //0x8
|
||||
};
|
||||
|
||||
static_assert(sizeof(_STRING) == 0x10);
|
||||
|
||||
struct _RTL_DRIVE_LETTER_CURDIR
|
||||
{
|
||||
USHORT Flags; //0x0
|
||||
USHORT Length; //0x2
|
||||
ULONG TimeStamp; //0x4
|
||||
struct _STRING DosPath; //0x8
|
||||
};
|
||||
|
||||
static_assert(sizeof(_RTL_DRIVE_LETTER_CURDIR) == 0x18);
|
||||
|
||||
struct _RTL_USER_PROCESS_PARAMETERS
|
||||
{
|
||||
ULONG MaximumLength; //0x0
|
||||
ULONG Length; //0x4
|
||||
ULONG Flags; //0x8
|
||||
ULONG DebugFlags; //0xc
|
||||
VOID* ConsoleHandle; //0x10
|
||||
ULONG ConsoleFlags; //0x18
|
||||
VOID* StandardInput; //0x20
|
||||
VOID* StandardOutput; //0x28
|
||||
VOID* StandardError; //0x30
|
||||
struct _CURDIR CurrentDirectory; //0x38
|
||||
struct _UNICODE_STRING DllPath; //0x50
|
||||
struct _UNICODE_STRING ImagePathName; //0x60
|
||||
struct _UNICODE_STRING CommandLine; //0x70
|
||||
VOID* Environment; //0x80
|
||||
ULONG StartingX; //0x88
|
||||
ULONG StartingY; //0x8c
|
||||
ULONG CountX; //0x90
|
||||
ULONG CountY; //0x94
|
||||
ULONG CountCharsX; //0x98
|
||||
ULONG CountCharsY; //0x9c
|
||||
ULONG FillAttribute; //0xa0
|
||||
ULONG WindowFlags; //0xa4
|
||||
ULONG ShowWindowFlags; //0xa8
|
||||
struct _UNICODE_STRING WindowTitle; //0xb0
|
||||
struct _UNICODE_STRING DesktopInfo; //0xc0
|
||||
struct _UNICODE_STRING ShellInfo; //0xd0
|
||||
struct _UNICODE_STRING RuntimeData; //0xe0
|
||||
struct _RTL_DRIVE_LETTER_CURDIR CurrentDirectores[32]; //0xf0
|
||||
ULONGLONG EnvironmentSize; //0x3f0
|
||||
ULONGLONG EnvironmentVersion; //0x3f8
|
||||
VOID* PackageDependencyData; //0x400
|
||||
ULONG ProcessGroupId; //0x408
|
||||
ULONG LoaderThreads; //0x40c
|
||||
struct _UNICODE_STRING RedirectionDllName; //0x410
|
||||
struct _UNICODE_STRING HeapPartitionName; //0x420
|
||||
ULONGLONG* DefaultThreadpoolCpuSetMasks; //0x430
|
||||
ULONG DefaultThreadpoolCpuSetMaskCount; //0x438
|
||||
ULONG DefaultThreadpoolThreadMaximum; //0x43c
|
||||
ULONG HeapMemoryTypeMask; //0x440
|
||||
};
|
||||
|
||||
static_assert(sizeof(_RTL_USER_PROCESS_PARAMETERS) == 0x448);
|
||||
|
||||
struct _PEB
|
||||
{
|
||||
UCHAR InheritedAddressSpace; //0x0
|
||||
UCHAR ReadImageFileExecOptions; //0x1
|
||||
UCHAR BeingDebugged; //0x2
|
||||
|
||||
union
|
||||
{
|
||||
UCHAR BitField; //0x3
|
||||
|
||||
struct
|
||||
{
|
||||
UCHAR ImageUsesLargePages : 1; //0x3
|
||||
UCHAR IsProtectedProcess : 1; //0x3
|
||||
UCHAR IsImageDynamicallyRelocated : 1; //0x3
|
||||
UCHAR SkipPatchingUser32Forwarders : 1; //0x3
|
||||
UCHAR IsPackagedProcess : 1; //0x3
|
||||
UCHAR IsAppContainer : 1; //0x3
|
||||
UCHAR IsProtectedProcessLight : 1; //0x3
|
||||
UCHAR IsLongPathAwareProcess : 1; //0x3
|
||||
};
|
||||
};
|
||||
|
||||
UCHAR Padding0[4]; //0x4
|
||||
VOID* Mutant; //0x8
|
||||
VOID* ImageBaseAddress; //0x10
|
||||
struct _PEB_LDR_DATA* Ldr; //0x18
|
||||
struct _RTL_USER_PROCESS_PARAMETERS* ProcessParameters; //0x20
|
||||
VOID* SubSystemData; //0x28
|
||||
VOID* ProcessHeap; //0x30
|
||||
struct _RTL_CRITICAL_SECTION* FastPebLock; //0x38
|
||||
union _SLIST_HEADER* volatile AtlThunkSListPtr; //0x40
|
||||
VOID* IFEOKey; //0x48
|
||||
|
||||
union
|
||||
{
|
||||
ULONG CrossProcessFlags; //0x50
|
||||
|
||||
struct
|
||||
{
|
||||
ULONG ProcessInJob : 1; //0x50
|
||||
ULONG ProcessInitializing : 1; //0x50
|
||||
ULONG ProcessUsingVEH : 1; //0x50
|
||||
ULONG ProcessUsingVCH : 1; //0x50
|
||||
ULONG ProcessUsingFTH : 1; //0x50
|
||||
ULONG ProcessPreviouslyThrottled : 1; //0x50
|
||||
ULONG ProcessCurrentlyThrottled : 1; //0x50
|
||||
ULONG ProcessImagesHotPatched : 1; //0x50
|
||||
ULONG ReservedBits0 : 24; //0x50
|
||||
};
|
||||
};
|
||||
|
||||
UCHAR Padding1[4]; //0x54
|
||||
|
||||
union
|
||||
{
|
||||
VOID* KernelCallbackTable; //0x58
|
||||
VOID* UserSharedInfoPtr; //0x58
|
||||
};
|
||||
|
||||
ULONG SystemReserved; //0x60
|
||||
ULONG AtlThunkSListPtr32; //0x64
|
||||
VOID* ApiSetMap; //0x68
|
||||
ULONG TlsExpansionCounter; //0x70
|
||||
UCHAR Padding2[4]; //0x74
|
||||
struct _RTL_BITMAP* TlsBitmap; //0x78
|
||||
ULONG TlsBitmapBits[2]; //0x80
|
||||
VOID* ReadOnlySharedMemoryBase; //0x88
|
||||
VOID* SharedData; //0x90
|
||||
VOID** ReadOnlyStaticServerData; //0x98
|
||||
VOID* AnsiCodePageData; //0xa0
|
||||
VOID* OemCodePageData; //0xa8
|
||||
VOID* UnicodeCaseTableData; //0xb0
|
||||
ULONG NumberOfProcessors; //0xb8
|
||||
ULONG NtGlobalFlag; //0xbc
|
||||
union _LARGE_INTEGER CriticalSectionTimeout; //0xc0
|
||||
ULONGLONG HeapSegmentReserve; //0xc8
|
||||
ULONGLONG HeapSegmentCommit; //0xd0
|
||||
ULONGLONG HeapDeCommitTotalFreeThreshold; //0xd8
|
||||
ULONGLONG HeapDeCommitFreeBlockThreshold; //0xe0
|
||||
ULONG NumberOfHeaps; //0xe8
|
||||
ULONG MaximumNumberOfHeaps; //0xec
|
||||
VOID** ProcessHeaps; //0xf0
|
||||
VOID* GdiSharedHandleTable; //0xf8
|
||||
VOID* ProcessStarterHelper; //0x100
|
||||
ULONG GdiDCAttributeList; //0x108
|
||||
UCHAR Padding3[4]; //0x10c
|
||||
struct _RTL_CRITICAL_SECTION* LoaderLock; //0x110
|
||||
ULONG OSMajorVersion; //0x118
|
||||
ULONG OSMinorVersion; //0x11c
|
||||
USHORT OSBuildNumber; //0x120
|
||||
USHORT OSCSDVersion; //0x122
|
||||
ULONG OSPlatformId; //0x124
|
||||
ULONG ImageSubsystem; //0x128
|
||||
ULONG ImageSubsystemMajorVersion; //0x12c
|
||||
ULONG ImageSubsystemMinorVersion; //0x130
|
||||
UCHAR Padding4[4]; //0x134
|
||||
ULONGLONG ActiveProcessAffinityMask; //0x138
|
||||
ULONG GdiHandleBuffer[60]; //0x140
|
||||
VOID(*PostProcessInitRoutine)
|
||||
(); //0x230
|
||||
struct _RTL_BITMAP* TlsExpansionBitmap; //0x238
|
||||
ULONG TlsExpansionBitmapBits[32]; //0x240
|
||||
ULONG SessionId; //0x2c0
|
||||
UCHAR Padding5[4]; //0x2c4
|
||||
union _ULARGE_INTEGER AppCompatFlags; //0x2c8
|
||||
union _ULARGE_INTEGER AppCompatFlagsUser; //0x2d0
|
||||
VOID* pShimData; //0x2d8
|
||||
VOID* AppCompatInfo; //0x2e0
|
||||
struct _UNICODE_STRING CSDVersion; //0x2e8
|
||||
struct _ACTIVATION_CONTEXT_DATA* ActivationContextData; //0x2f8
|
||||
struct _ASSEMBLY_STORAGE_MAP* ProcessAssemblyStorageMap; //0x300
|
||||
struct _ACTIVATION_CONTEXT_DATA* SystemDefaultActivationContextData; //0x308
|
||||
struct _ASSEMBLY_STORAGE_MAP* SystemAssemblyStorageMap; //0x310
|
||||
ULONGLONG MinimumStackCommit; //0x318
|
||||
VOID* SparePointers[2]; //0x320
|
||||
VOID* PatchLoaderData; //0x330
|
||||
struct _CHPEV2_PROCESS_INFO* ChpeV2ProcessInfo; //0x338
|
||||
ULONG AppModelFeatureState; //0x340
|
||||
ULONG SpareUlongs[2]; //0x344
|
||||
USHORT ActiveCodePage; //0x34c
|
||||
USHORT OemCodePage; //0x34e
|
||||
USHORT UseCaseMapping; //0x350
|
||||
USHORT UnusedNlsField; //0x352
|
||||
VOID* WerRegistrationData; //0x358
|
||||
VOID* WerShipAssertPtr; //0x360
|
||||
VOID* EcCodeBitMap; //0x368
|
||||
VOID* pImageHeaderHash; //0x370
|
||||
|
||||
union
|
||||
{
|
||||
ULONG TracingFlags; //0x378
|
||||
|
||||
struct
|
||||
{
|
||||
ULONG HeapTracingEnabled : 1; //0x378
|
||||
ULONG CritSecTracingEnabled : 1; //0x378
|
||||
ULONG LibLoaderTracingEnabled : 1; //0x378
|
||||
ULONG SpareTracingBits : 29; //0x378
|
||||
};
|
||||
};
|
||||
|
||||
UCHAR Padding6[4]; //0x37c
|
||||
ULONGLONG CsrServerReadOnlySharedMemoryBase; //0x380
|
||||
ULONGLONG TppWorkerpListLock; //0x388
|
||||
struct _LIST_ENTRY TppWorkerpList; //0x390
|
||||
VOID* WaitOnAddressHashTable[128]; //0x3a0
|
||||
VOID* TelemetryCoverageHeader; //0x7a0
|
||||
ULONG CloudFileFlags; //0x7a8
|
||||
ULONG CloudFileDiagFlags; //0x7ac
|
||||
CHAR PlaceholderCompatibilityMode; //0x7b0
|
||||
CHAR PlaceholderCompatibilityModeReserved[7]; //0x7b1
|
||||
struct _LEAP_SECOND_DATA* LeapSecondData; //0x7b8
|
||||
|
||||
union
|
||||
{
|
||||
ULONG LeapSecondFlags; //0x7c0
|
||||
|
||||
struct
|
||||
{
|
||||
ULONG SixtySecondEnabled : 1; //0x7c0
|
||||
ULONG Reserved : 31; //0x7c0
|
||||
};
|
||||
};
|
||||
|
||||
ULONG NtGlobalFlag2; //0x7c4
|
||||
ULONGLONG ExtendedFeatureDisableMask; //0x7c8
|
||||
};
|
||||
|
||||
static_assert(sizeof(_PEB) == 0x7d0);
|
||||
|
||||
struct _CLIENT_ID
|
||||
{
|
||||
PVOID UniqueProcess; // 0x0
|
||||
PVOID UniqueThread; // 0x8
|
||||
};
|
||||
|
||||
static_assert(sizeof(_CLIENT_ID) == 0x10);
|
||||
|
||||
struct _GDI_TEB_BATCH
|
||||
{
|
||||
ULONG Offset : 31; //0x0
|
||||
ULONG HasRenderingCommand : 1; //0x0
|
||||
ULONGLONG HDC; //0x8
|
||||
ULONG Buffer[310]; //0x10
|
||||
};
|
||||
|
||||
static_assert(sizeof(_GDI_TEB_BATCH) == 0x4E8);
|
||||
|
||||
struct _ACTIVATION_CONTEXT_STACK
|
||||
{
|
||||
struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME* ActiveFrame; //0x0
|
||||
struct _LIST_ENTRY FrameListCache; //0x8
|
||||
ULONG Flags; //0x18
|
||||
ULONG NextCookieSequenceNumber; //0x1c
|
||||
ULONG StackId; //0x20
|
||||
};
|
||||
|
||||
static_assert(sizeof(_ACTIVATION_CONTEXT_STACK) == 0x28);
|
||||
|
||||
struct _TEB
|
||||
{
|
||||
struct _NT_TIB NtTib; //0x0
|
||||
VOID* EnvironmentPointer; //0x38
|
||||
struct _CLIENT_ID ClientId; //0x40
|
||||
VOID* ActiveRpcHandle; //0x50
|
||||
VOID* ThreadLocalStoragePointer; //0x58
|
||||
struct _PEB* ProcessEnvironmentBlock; //0x60
|
||||
ULONG LastErrorValue; //0x68
|
||||
ULONG CountOfOwnedCriticalSections; //0x6c
|
||||
VOID* CsrClientThread; //0x70
|
||||
VOID* Win32ThreadInfo; //0x78
|
||||
ULONG User32Reserved[26]; //0x80
|
||||
ULONG UserReserved[5]; //0xe8
|
||||
VOID* WOW32Reserved; //0x100
|
||||
ULONG CurrentLocale; //0x108
|
||||
ULONG FpSoftwareStatusRegister; //0x10c
|
||||
VOID* ReservedForDebuggerInstrumentation[16]; //0x110
|
||||
VOID* SystemReserved1[30]; //0x190
|
||||
CHAR PlaceholderCompatibilityMode; //0x280
|
||||
UCHAR PlaceholderHydrationAlwaysExplicit; //0x281
|
||||
CHAR PlaceholderReserved[10]; //0x282
|
||||
ULONG ProxiedProcessId; //0x28c
|
||||
struct _ACTIVATION_CONTEXT_STACK _ActivationStack; //0x290
|
||||
UCHAR WorkingOnBehalfTicket[8]; //0x2b8
|
||||
LONG ExceptionCode; //0x2c0
|
||||
UCHAR Padding0[4]; //0x2c4
|
||||
struct _ACTIVATION_CONTEXT_STACK* ActivationContextStackPointer; //0x2c8
|
||||
ULONGLONG InstrumentationCallbackSp; //0x2d0
|
||||
ULONGLONG InstrumentationCallbackPreviousPc; //0x2d8
|
||||
ULONGLONG InstrumentationCallbackPreviousSp; //0x2e0
|
||||
ULONG TxFsContext; //0x2e8
|
||||
UCHAR InstrumentationCallbackDisabled; //0x2ec
|
||||
UCHAR UnalignedLoadStoreExceptions; //0x2ed
|
||||
UCHAR Padding1[2]; //0x2ee
|
||||
struct _GDI_TEB_BATCH GdiTebBatch; //0x2f0
|
||||
struct _CLIENT_ID RealClientId; //0x7d8
|
||||
VOID* GdiCachedProcessHandle; //0x7e8
|
||||
ULONG GdiClientPID; //0x7f0
|
||||
ULONG GdiClientTID; //0x7f4
|
||||
VOID* GdiThreadLocalInfo; //0x7f8
|
||||
ULONGLONG Win32ClientInfo[62]; //0x800
|
||||
VOID* glDispatchTable[233]; //0x9f0
|
||||
ULONGLONG glReserved1[29]; //0x1138
|
||||
VOID* glReserved2; //0x1220
|
||||
VOID* glSectionInfo; //0x1228
|
||||
VOID* glSection; //0x1230
|
||||
VOID* glTable; //0x1238
|
||||
VOID* glCurrentRC; //0x1240
|
||||
VOID* glContext; //0x1248
|
||||
ULONG LastStatusValue; //0x1250
|
||||
UCHAR Padding2[4]; //0x1254
|
||||
struct _UNICODE_STRING StaticUnicodeString; //0x1258
|
||||
WCHAR StaticUnicodeBuffer[261]; //0x1268
|
||||
UCHAR Padding3[6]; //0x1472
|
||||
VOID* DeallocationStack; //0x1478
|
||||
VOID* TlsSlots[64]; //0x1480
|
||||
struct _LIST_ENTRY TlsLinks; //0x1680
|
||||
VOID* Vdm; //0x1690
|
||||
VOID* ReservedForNtRpc; //0x1698
|
||||
VOID* DbgSsReserved[2]; //0x16a0
|
||||
ULONG HardErrorMode; //0x16b0
|
||||
UCHAR Padding4[4]; //0x16b4
|
||||
VOID* Instrumentation[11]; //0x16b8
|
||||
struct _GUID ActivityId; //0x1710
|
||||
VOID* SubProcessTag; //0x1720
|
||||
VOID* PerflibData; //0x1728
|
||||
VOID* EtwTraceData; //0x1730
|
||||
VOID* WinSockData; //0x1738
|
||||
ULONG GdiBatchCount; //0x1740
|
||||
|
||||
union
|
||||
{
|
||||
struct _PROCESSOR_NUMBER CurrentIdealProcessor; //0x1744
|
||||
ULONG IdealProcessorValue; //0x1744
|
||||
|
||||
struct
|
||||
{
|
||||
UCHAR ReservedPad0; //0x1744
|
||||
UCHAR ReservedPad1; //0x1745
|
||||
UCHAR ReservedPad2; //0x1746
|
||||
UCHAR IdealProcessor; //0x1747
|
||||
};
|
||||
};
|
||||
|
||||
ULONG GuaranteedStackBytes; //0x1748
|
||||
UCHAR Padding5[4]; //0x174c
|
||||
VOID* ReservedForPerf; //0x1750
|
||||
VOID* ReservedForOle; //0x1758
|
||||
ULONG WaitingOnLoaderLock; //0x1760
|
||||
UCHAR Padding6[4]; //0x1764
|
||||
VOID* SavedPriorityState; //0x1768
|
||||
ULONGLONG ReservedForCodeCoverage; //0x1770
|
||||
VOID* ThreadPoolData; //0x1778
|
||||
VOID** TlsExpansionSlots; //0x1780
|
||||
struct _CHPEV2_CPUAREA_INFO* ChpeV2CpuAreaInfo; //0x1788
|
||||
VOID* Unused; //0x1790
|
||||
ULONG MuiGeneration; //0x1798
|
||||
ULONG IsImpersonating; //0x179c
|
||||
VOID* NlsCache; //0x17a0
|
||||
VOID* pShimData; //0x17a8
|
||||
ULONG HeapData; //0x17b0
|
||||
UCHAR Padding7[4]; //0x17b4
|
||||
VOID* CurrentTransactionHandle; //0x17b8
|
||||
struct _TEB_ACTIVE_FRAME* ActiveFrame; //0x17c0
|
||||
VOID* FlsData; //0x17c8
|
||||
VOID* PreferredLanguages; //0x17d0
|
||||
VOID* UserPrefLanguages; //0x17d8
|
||||
VOID* MergedPrefLanguages; //0x17e0
|
||||
ULONG MuiImpersonation; //0x17e8
|
||||
|
||||
union
|
||||
{
|
||||
volatile USHORT CrossTebFlags; //0x17ec
|
||||
USHORT SpareCrossTebBits : 16; //0x17ec
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
USHORT SameTebFlags; //0x17ee
|
||||
|
||||
struct
|
||||
{
|
||||
USHORT SafeThunkCall : 1; //0x17ee
|
||||
USHORT InDebugPrint : 1; //0x17ee
|
||||
USHORT HasFiberData : 1; //0x17ee
|
||||
USHORT SkipThreadAttach : 1; //0x17ee
|
||||
USHORT WerInShipAssertCode : 1; //0x17ee
|
||||
USHORT RanProcessInit : 1; //0x17ee
|
||||
USHORT ClonedThread : 1; //0x17ee
|
||||
USHORT SuppressDebugMsg : 1; //0x17ee
|
||||
USHORT DisableUserStackWalk : 1; //0x17ee
|
||||
USHORT RtlExceptionAttached : 1; //0x17ee
|
||||
USHORT InitialThread : 1; //0x17ee
|
||||
USHORT SessionAware : 1; //0x17ee
|
||||
USHORT LoadOwner : 1; //0x17ee
|
||||
USHORT LoaderWorker : 1; //0x17ee
|
||||
USHORT SkipLoaderInit : 1; //0x17ee
|
||||
USHORT SkipFileAPIBrokering : 1; //0x17ee
|
||||
};
|
||||
};
|
||||
|
||||
VOID* TxnScopeEnterCallback; //0x17f0
|
||||
VOID* TxnScopeExitCallback; //0x17f8
|
||||
VOID* TxnScopeContext; //0x1800
|
||||
ULONG LockCount; //0x1808
|
||||
LONG WowTebOffset; //0x180c
|
||||
VOID* ResourceRetValue; //0x1810
|
||||
VOID* ReservedForWdf; //0x1818
|
||||
ULONGLONG ReservedForCrt; //0x1820
|
||||
struct _GUID EffectiveContainerId; //0x1828
|
||||
ULONGLONG LastSleepCounter; //0x1838
|
||||
ULONG SpinCallCount; //0x1840
|
||||
UCHAR Padding8[4]; //0x1844
|
||||
ULONGLONG ExtendedFeatureDisableMask; //0x1848
|
||||
};
|
||||
|
||||
static_assert(sizeof(_TEB) == 0x1850);
|
||||
#pragma endregion
|
||||
Reference in New Issue
Block a user