#include "STDInclude.hpp" namespace Components { Utils::Signal Renderer::FrameSignal; Utils::Signal Renderer::FrameOnceSignal; Utils::Signal Renderer::BackendFrameSignal; Utils::Signal Renderer::EndRecoverDeviceSignal; Utils::Signal Renderer::BeginRecoverDeviceSignal; std::vector Renderer::DelayedSlots; __declspec(naked) void Renderer::FrameStub() { __asm { pushad call Renderer::FrameHandler popad push 5AC950h retn } } void Renderer::FrameHandler() { Renderer::DelaySignal(); Renderer::FrameSignal(); Utils::Signal copy(Renderer::FrameOnceSignal); Renderer::FrameOnceSignal.clear(); copy(); } __declspec(naked) void Renderer::BackendFrameStub() { __asm { pushad call Renderer::BackendFrameHandler popad mov eax, ds:66E1BF0h push 536A85h retn } } void Renderer::BackendFrameHandler() { IDirect3DDevice9* device = *Game::dx_ptr; if (device) { device->AddRef(); Renderer::BackendFrameSignal(device); device->Release(); } } void Renderer::Once(Utils::Slot callback) { if (Dedicated::IsEnabled()) return; Renderer::FrameOnceSignal.connect(callback); } void Renderer::OnFrame(Utils::Slot callback) { if (Dedicated::IsEnabled()) return; Renderer::FrameSignal.connect(callback); } void Renderer::OnBackendFrame(Utils::Slot callback) { Renderer::BackendFrameSignal.connect(callback); } void Renderer::OnDeviceRecoveryEnd(Utils::Slot callback) { Renderer::EndRecoverDeviceSignal.connect(callback); } void Renderer::OnDeviceRecoveryBegin(Utils::Slot callback) { Renderer::BeginRecoverDeviceSignal.connect(callback); } void Renderer::OnDelay(Utils::Slot callback, std::chrono::nanoseconds delay) { Renderer::DelayedSlot slot; slot.callback = callback; slot.delay = delay; Renderer::DelayedSlots.push_back(slot); } void Renderer::DelaySignal() { Utils::Signal signal; for(auto i = Renderer::DelayedSlots.begin(); i != Renderer::DelayedSlots.end();) { if(i->interval.elapsed(i->delay)) { signal.connect(i->callback); i = Renderer::DelayedSlots.erase(i); continue; } ++i; } signal(); } int Renderer::Width() { return Utils::Hook::Get(0x66E1C68); } int Renderer::Height() { return Utils::Hook::Get(0x66E1C6C); } Renderer::Renderer() { if (Dedicated::IsEnabled()) return; // Renderer::OnBackendFrame([] (IDirect3DDevice9* device) // { // if (Game::Sys_Milliseconds() % 2) // { // device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, 0, 0, 0); // } // // return; // // IDirect3DSurface9* buffer = nullptr; // // device->CreateOffscreenPlainSurface(Renderer::Width(), Renderer::Height(), D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &buffer, nullptr); // device->GetFrontBufferData(0, buffer); // // if (buffer) // { // D3DSURFACE_DESC desc; // D3DLOCKED_RECT lockedRect; // // buffer->GetDesc(&desc); // // HRESULT res = buffer->LockRect(&lockedRect, NULL, D3DLOCK_READONLY); // // // buffer->UnlockRect(); // } // }); // Frame hook Utils::Hook(0x5ACB99, Renderer::FrameStub, HOOK_CALL).install()->quick(); Utils::Hook(0x536A80, Renderer::BackendFrameStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x508298, [] () { Game::DB_BeginRecoverLostDevice(); Renderer::BeginRecoverDeviceSignal(); }, HOOK_CALL).install()->quick(); Utils::Hook(0x508355, [] () { Renderer::EndRecoverDeviceSignal(); Game::DB_EndRecoverLostDevice(); }, HOOK_CALL).install()->quick(); } Renderer::~Renderer() { Renderer::BackendFrameSignal.clear(); Renderer::FrameOnceSignal.clear(); Renderer::FrameSignal.clear(); Renderer::EndRecoverDeviceSignal.clear(); Renderer::BeginRecoverDeviceSignal.clear(); } }