﻿// dllmain.cpp - Roblox Render Thread Hook
// Derle: cl /O2 /MT /LD /Fe:rbxhook.dll dllmain.cpp /link kernel32.lib user32.lib d3d11.lib dxgi.lib psapi.lib
#include <windows.h>
#include <d3d11.h>
#include <dxgi.h>
#include <intrin.h>
#include <tlhelp32.h>      // CreateToolhelp32Snapshot, THREADENTRY32, vb.
#include <psapi.h>         // GetModuleInformation, MODULEINFO

#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "psapi.lib")

// === GLOBALS ===
static ID3D11Device* g_Device = nullptr;
static ID3D11DeviceContext* g_Context = nullptr;
static IDXGISwapChain* g_SwapChain = nullptr;

static void* g_OriginalPresent = nullptr;

// === DETOUR HELPER ===
static void* DetourFunc(void* target, void* hook, size_t len)
{
    DWORD oldProtect;
    VirtualProtect(target, len, PAGE_EXECUTE_READWRITE, &oldProtect);

    void* gateway = VirtualAlloc(0, len + 14, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    memcpy(gateway, target, len);
    *(BYTE*)((ULONG_PTR)gateway + len) = 0xE9;
    *(DWORD*)((ULONG_PTR)gateway + len + 1) = (DWORD)((ULONG_PTR)target + len - ((ULONG_PTR)gateway + len + 5));

    memset(target, 0x90, len);
    *(BYTE*)target = 0xE9;
    *(DWORD*)((ULONG_PTR)target + 1) = (DWORD)((ULONG_PTR)hook - ((ULONG_PTR)target + 5));

    VirtualProtect(target, len, oldProtect, &oldProtect);
    return gateway;
}

// === HOOKED PRESENT ===
typedef HRESULT(WINAPI* Present_t)(IDXGISwapChain*, UINT, UINT);

static HRESULT WINAPI HookedPresent(IDXGISwapChain* swapChain, UINT syncInterval, UINT flags)
{
    syncInterval = 0;
    flags |= DXGI_PRESENT_DO_NOT_WAIT;

    static BOOL first = TRUE;
    if (first && g_SwapChain == nullptr) {
        first = FALSE;
        g_SwapChain = swapChain;

        swapChain->GetDevice(__uuidof(ID3D11Device), (void**)&g_Device);
        if (g_Device) {
            g_Device->GetImmediateContext(&g_Context);

            IDXGIDevice1* dxgiDevice = nullptr;
            if (SUCCEEDED(g_Device->QueryInterface(__uuidof(IDXGIDevice1), (void**)&dxgiDevice))) {
                dxgiDevice->SetMaximumFrameLatency(1);
                dxgiDevice->Release();
            }
        }
    }

    return ((Present_t)g_OriginalPresent)(swapChain, syncInterval, flags);
}

// === MEMORY POOL OPTIMIZATION ===
static void OptimizeMemoryPools()
{
    HMODULE hMod = GetModuleHandleA("RobloxPlayerBeta.exe");
    if (!hMod) hMod = GetModuleHandleA("Windows10Universal.exe");
    if (!hMod) return;

    BYTE pattern[] = { 0xF3, 0x0F, 0x10, 0x05 };

    MODULEINFO modInfo;
    ZeroMemory(&modInfo, sizeof(modInfo));

    if (!GetModuleInformation(GetCurrentProcess(), hMod, &modInfo, sizeof(modInfo))) return;

    BYTE* base = (BYTE*)modInfo.lpBaseOfDll;
    SIZE_T size = modInfo.SizeOfImage;

    for (SIZE_T i = 0; i < size - sizeof(pattern); i++) {
        if (memcmp(base + i, pattern, 4) == 0) {
            DWORD oldProtect;
            VirtualProtect(base + i + 12, 6, PAGE_EXECUTE_READWRITE, &oldProtect);
            memset(base + i + 12, 0x90, 6);
            VirtualProtect(base + i + 12, 6, oldProtect, &oldProtect);
            break;
        }
    }
}

// === RENDER THREAD PRIORITY BOOST ===
static void BoostRenderThread()
{
    DWORD pid = GetCurrentProcessId();
    HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (snap == INVALID_HANDLE_VALUE) return;

    THREADENTRY32 te;
    ZeroMemory(&te, sizeof(te));
    te.dwSize = sizeof(THREADENTRY32);

    if (Thread32First(snap, &te)) {
        do {
            if (te.th32OwnerProcessID == pid) {
                HANDLE hThread = OpenThread(THREAD_SET_INFORMATION | THREAD_QUERY_INFORMATION,
                    FALSE, te.th32ThreadID);
                if (hThread) {
                    SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
                    CloseHandle(hThread);
                }
            }
        } while (Thread32Next(snap, &te));
    }

    CloseHandle(snap);
}

// === DLL MAIN ===
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved)
{
    if (reason != DLL_PROCESS_ATTACH) return TRUE;

    DisableThreadLibraryCalls(hModule);

    HMODULE hDXGI = GetModuleHandleA("dxgi.dll");
    if (hDXGI) {
        void* presentAddr = GetProcAddress(hDXGI, "Present");
        if (presentAddr) {
            g_OriginalPresent = DetourFunc(presentAddr, HookedPresent, 5);
        }
    }

    OptimizeMemoryPools();
    BoostRenderThread();

    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);

    typedef LONG(NTAPI* pNtSetTimerResolution)(ULONG, BOOLEAN, PULONG);
    HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
    pNtSetTimerResolution NtSetTimerResolution = (pNtSetTimerResolution)GetProcAddress(hNtdll, "NtSetTimerResolution");
    if (NtSetTimerResolution) {
        ULONG actual;
        NtSetTimerResolution(5000, TRUE, &actual);
    }

    return TRUE;
}