diff --git a/include/RE/R/Renderer.h b/include/RE/R/Renderer.h index a737492fd..cb663df00 100644 --- a/include/RE/R/Renderer.h +++ b/include/RE/R/Renderer.h @@ -39,22 +39,20 @@ namespace RE { public: // members - std::uint32_t uiAdapter; // 0000 - std::uint32_t unk04; // 0004 - refreshRate? - std::uint32_t unk08; // 0008 - std::uint32_t unk0C; // 000C - std::uint32_t unk10; // 0010 - std::uint32_t unk14; // 0014 - std::uint32_t unk18; // 0018 - std::uint32_t unk1C; // 001C + std::uint32_t adapter; // 0000 + DirectX::DXGI_RATIONAL desiredRefreshRate; // 0004 + DirectX::DXGI_RATIONAL actualRefreshRate; // 000C + DirectX::DXGI_MODE_SCALING scaleMode; // 0014 + DirectX::DXGI_MODE_SCANLINE_ORDER scanlineOrdering; // 0018 + std::uint32_t isNotWindowed; // 001C bool fullScreen; // 0020 bool borderlessDisplay; // 0021 bool readOnlyDepth; // 0022 - std::uint8_t unk23; // 0023 - std::uint8_t unk24; // 0024 - std::uint32_t unk28; // 0028 - std::uint32_t unk30; // 0030 - std::uint32_t presentInterval; // 0034 + bool instantiated; // 0023 + bool requestedWindowSizeChange; // 0024 + std::uint32_t newWidth; // 0028 + std::uint32_t newHeight; // 002C + std::uint32_t presentInterval; // 0030 ID3D11Device* forwarder; // 0038 ID3D11DeviceContext* context; // 0040 RendererWindow renderWindows[32]; // 0048 @@ -70,14 +68,70 @@ namespace RE }; static_assert(offsetof(RendererData, lock) == 0x2780); + struct RendererInitOSData + { + WinAPI::HWND hwnd; // 00 + WinAPI::HINSTANCE instance; // 08 + WinAPI::WNDPROC windowProcFunction; // 10 + WinAPI::HICON icon; // 18 + const char* className; // 20 + uint32_t adapter; // 28 + uint32_t unk2C; // 2C + }; + static_assert(sizeof(RendererInitOSData) == 0x30); + + struct ScreenSize + { + uint32_t width; // 00 + uint32_t height; // 04 + }; + static_assert(sizeof(ScreenSize) == 0x8); + + struct ApplicationWindowProperties + { + ScreenSize screenSize; // 00 + int windowX; // 08 + int windowY; // 0C + int refreshRate; // 10 + int presentInterval; // 14 + bool appFullScreen; // 18 + bool borderlessWindow; // 19 + bool vsync; // 1A + }; + static_assert(sizeof(ApplicationWindowProperties) == 0x1C); + class Renderer { public: [[nodiscard]] static Renderer* GetSingleton() noexcept; + void CreateSwapChain(WinAPI::HWND* window, bool setCurrent); + void KillWindow(std::uint32_t windowID); + void Lock(); + void Unlock(); + void ResizeWindow(std::uint32_t windowID, std::uint32_t width, std::uint32_t height, bool fullscreen, bool borderless); + void RequestWindowResize(std::uint32_t width, std::uint32_t height); + void SetWindowPosition(std::uint32_t windowID, std::int32_t x, std::int32_t y); + void SetWindowActiveState(bool show); + void WindowSizeChanged(std::uint32_t windowID); + void ResetWindow(std::uint32_t windowID); + void UpdateViewPort(std::uint32_t a_unk, std::uint32_t b_unk, bool c_unk); + [[nodiscard]] NiTexture::RendererData* CreateRenderTexture(std::uint32_t a_width, std::uint32_t a_height); void SaveRenderTargetToFile(RENDER_TARGET a_renderTarget, const char* a_filePath, TextureFileFormat a_textureFileFormat); + [[nodiscard]] static RendererData* GetRendererData(); + [[nodiscard]] static ScreenSize GetScreenSize(); + [[nodiscard]] static ID3D11Device* GetDevice(); + [[nodiscard]] static RendererWindow* GetCurrentRenderWindow(); + + private: + void Begin(std::uint32_t windowID); + void Init(RendererInitOSData* a_data, ApplicationWindowProperties* windowProps, WinAPI::HWND window); + void End(); + void Shutdown(); + + public: // members std::uint64_t unk00; // 00 std::uint64_t unk08; // 08 diff --git a/include/SKSE/Impl/WinAPI.h b/include/SKSE/Impl/WinAPI.h index 8d13cf772..2507ced98 100644 --- a/include/SKSE/Impl/WinAPI.h +++ b/include/SKSE/Impl/WinAPI.h @@ -54,6 +54,11 @@ namespace SKSE::WinAPI struct HINSTANCE__; using HINSTANCE = HINSTANCE__*; + struct HICON__; + using HICON = HICON__*; + + using WNDPROC = std::int32_t(__stdcall*)(HWND, std::uint32_t, std::uint64_t, std::int64_t); + struct _WIN32_FIND_DATAA { public: @@ -524,4 +529,28 @@ namespace RE::DirectX float m[4][4]; }; static_assert(sizeof(XMFLOAT4X4) == 0x40); + + struct DXGI_RATIONAL + { + public: + // members + std::uint32_t numerator; // 00 + std::uint32_t denominator; // 04 + }; + static_assert(sizeof(DXGI_RATIONAL) == 0x08); + + enum DXGI_MODE_SCALING : std::uint32_t + { + DXGI_MODE_SCALING_UNSPECIFIED = 0, + DXGI_MODE_SCALING_CENTERED = 1, + DXGI_MODE_SCALING_STRETCHED = 2 + }; + + enum DXGI_MODE_SCANLINE_ORDER : std::uint32_t + { + DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED = 0, + DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE = 1, + DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST = 2, + DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST = 3 + }; } diff --git a/src/RE/R/Renderer.cpp b/src/RE/R/Renderer.cpp index 7a7c2ca1e..a0c836949 100644 --- a/src/RE/R/Renderer.cpp +++ b/src/RE/R/Renderer.cpp @@ -23,5 +23,122 @@ namespace RE REL::Relocation func{ RELOCATION_ID(75522, 77316) }; return func(this, a_renderTarget, a_filePath, a_textureFileFormat); } + + void Renderer::Init(RendererInitOSData* a_data, ApplicationWindowProperties* windowProps, WinAPI::HWND window) + { + using func_t = decltype(&Renderer::Init); + REL::Relocation func{ RELOCATION_ID(75445, 77226) }; + return func(this, a_data, windowProps, window); + } + void Renderer::Begin(std::uint32_t windowID) + { + using func_t = decltype(&Renderer::Begin); + REL::Relocation func{ RELOCATION_ID(75460, 77245) }; + return func(this, windowID); + } + void Renderer::CreateSwapChain(WinAPI::HWND* window, bool setCurrent) + { + using func_t = decltype(&Renderer::CreateSwapChain); + REL::Relocation func{ RELOCATION_ID(75457, 77242) }; + return func(this, window, setCurrent); + } + void Renderer::End() + { + using func_t = decltype(&Renderer::End); + REL::Relocation func{ RELOCATION_ID(75461, 77246) }; + return func(this); + } + void Renderer::KillWindow(std::uint32_t windowID) + { + using func_t = decltype(&Renderer::KillWindow); + REL::Relocation func{ RELOCATION_ID(75452, 77237) }; + return func(this, windowID); + } + void Renderer::Lock() + { + using func_t = decltype(&Renderer::Lock); + REL::Relocation func{ RELOCATION_ID(75458, 77243) }; + return func(this); + } + void Renderer::Unlock() + { + using func_t = decltype(&Renderer::Unlock); + REL::Relocation func{ RELOCATION_ID(75459, 77244) }; + return func(this); + } + void Renderer::ResizeWindow(std::uint32_t windowID, std::uint32_t width, std::uint32_t height, bool fullscreen, bool borderless) + { + using func_t = decltype(&Renderer::ResizeWindow); + REL::Relocation func{ RELOCATION_ID(75454, 77239) }; + return func(this, windowID, width, height, fullscreen, borderless); + } + void Renderer::RequestWindowResize(std::uint32_t width, std::uint32_t height) + { + using func_t = decltype(&Renderer::RequestWindowResize); + REL::Relocation func{ RELOCATION_ID(75450, 77235) }; + return func(this, width, height); + } + void Renderer::SetWindowPosition(std::uint32_t windowID, std::int32_t x, std::int32_t y) + { + using func_t = decltype(&Renderer::SetWindowPosition); + REL::Relocation func{ RELOCATION_ID(75448, 77233) }; + return func(this, windowID, x, y); + } + void Renderer::SetWindowActiveState(bool show) + { + using func_t = decltype(&Renderer::SetWindowActiveState); + REL::Relocation func{ RELOCATION_ID(75451, 77236) }; + return func(this, show); + } + void Renderer::WindowSizeChanged(std::uint32_t windowID) + { + using func_t = decltype(&Renderer::WindowSizeChanged); + REL::Relocation func{ RELOCATION_ID(75453, 77238) }; + return func(this, windowID); + } + void Renderer::ResetWindow(std::uint32_t windowID) + { + using func_t = decltype(&Renderer::ResetWindow); + REL::Relocation func{ RELOCATION_ID(75454, 77239) }; + return func(this, windowID); + } + void Renderer::UpdateViewPort(std::uint32_t a_unk, std::uint32_t b_unk, bool c_unk) + { + using func_t = decltype(&Renderer::UpdateViewPort); + REL::Relocation func{ RELOCATION_ID(75455, 77240) }; + return func(this, a_unk, b_unk, c_unk); + } + void Renderer::Shutdown() + { + using func_t = decltype(&Renderer::Shutdown); + REL::Relocation func{ RELOCATION_ID(75447, 77228) }; + return func(this); + } + + [[nodiscard]] RendererData* Renderer::GetRendererData() + { + // Location is a global pointer to the RendererData in the Renderer singleton + REL::Relocation singleton{ RELOCATION_ID(524728, 411347) }; + return *singleton; + } + [[nodiscard]] ScreenSize Renderer::GetScreenSize() + { + // This is a global managed by Renderer, but not part of the RendererData struct. + // We pass back the value so users are not tempted to modify this directly. + REL::Relocation singleton{ RELOCATION_ID(525002, 411483) }; + return *singleton; + } + [[nodiscard]] ID3D11Device* Renderer::GetDevice() + { + // Location is a global pointer to the device in the Renderer Data + REL::Relocation device{ RELOCATION_ID(524729, 411348) }; + return *device; + } + [[nodiscard]] RendererWindow* Renderer::GetCurrentRenderWindow() + { + // Location is a global pointer to the current renderWindow (which is not necessarily at index 0 in the renderWindows array) + REL::Relocation renderWindow{ RELOCATION_ID(524730, 411349) }; + return *renderWindow; + } } }