Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 110 additions & 34 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,27 @@ cmake_minimum_required(VERSION 3.24.0)
project(Flarial)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")

set(CLIENT_VERSION "2.00") # Update this for every new release

set(CLIENT_BUILD_TYPE "Release")
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CLIENT_BUILD_TYPE "Debug")
add_compile_definitions(__DEBUG__)
elseif (CMAKE_BUILD_TYPE STREQUAL "Test")
set(CLIENT_BUILD_TYPE "Test")
add_compile_definitions(__TEST__)
get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if (IS_MULTI_CONFIG)
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;Test" CACHE STRING "Supported build configurations" FORCE)
else()
set(CLIENT_BUILD_TYPE "Release")
add_compile_definitions(__RELEASE__)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release Test)
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
endif()
endif()

set(CLIENT_VERSION "2.00") # Update this for every new release

set(FLARIAL_BUILD_TYPE_EXPR "$<IF:$<CONFIG:Debug>,Debug,$<IF:$<CONFIG:Test>,Test,Release>>")
add_compile_definitions(
$<$<CONFIG:Debug>:__DEBUG__>
$<$<CONFIG:Test>:__TEST__>
$<$<NOT:$<OR:$<CONFIG:Debug>,$<CONFIG:Test>>>:__RELEASE__>
)

execute_process(
COMMAND git rev-parse --short HEAD
OUTPUT_VARIABLE COMMIT_HASH
Expand Down Expand Up @@ -51,41 +57,105 @@ add_compile_options($<$<CONFIG:Release>:/Ob2>)

add_compile_options(/bigobj)
add_compile_options(/utf-8)
if (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "Test")
# Optimize for performance with debug info for symbolication
add_compile_options(/O2 /Oi /Gy /Gw /GF /fp:fast /Gd /MT /Ob2 /Zi)
# Generate PDB with optimizations preserved
add_link_options(/DEBUG /OPT:REF /OPT:ICF)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")
# Ignore debug runtime library to avoid conflicts
add_link_options(/NODEFAULTLIB:MSVCRTD)
elseif (CMAKE_BUILD_TYPE STREQUAL "Debug")
# Optimize for build time
add_compile_options(/Od /Zi /MT)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")
# Ignore debug runtime library to avoid conflicts
add_link_options(/NODEFAULTLIB:MSVCRTD)
endif()
add_compile_options(/FS)
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/EHsc>)

# Preserve the intended runtime / debug-info behavior for both single-config and multi-config generators.
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:Test>>:/fp:fast>)
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:Test>>:/Zi>)
add_compile_options($<$<CONFIG:Debug>:/Od>)
add_compile_options($<$<CONFIG:Debug>:/Zi>)
add_link_options($<$<OR:$<CONFIG:Release>,$<CONFIG:Test>>:/DEBUG>)
add_link_options($<$<OR:$<CONFIG:Release>,$<CONFIG:Test>>:/OPT:REF>)
add_link_options($<$<OR:$<CONFIG:Release>,$<CONFIG:Test>>:/OPT:ICF>)
add_link_options(/NODEFAULTLIB:MSVCRTD)

# Generate version and build date
string(TIMESTAMP BUILD_DATE "%Y-%m-%d %H:%M:%S" UTC)
set(FLARIAL_BUILD_DATE "${BUILD_DATE}")

add_compile_definitions(
FLARIAL_VERSION=\"${CLIENT_VERSION}\"
FLARIAL_BUILD_TYPE=\"${CLIENT_BUILD_TYPE}\"
FLARIAL_BUILD_TYPE=\"${FLARIAL_BUILD_TYPE_EXPR}\"
FLARIAL_BUILD_DATE=\"${FLARIAL_BUILD_DATE}\"
)

file(GLOB_RECURSE SOURCE_FILES "src/*.cpp" "src/*.hpp")
file(GLOB_RECURSE LIB_FILES "lib/*.cpp" "lib/*.h")
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS "src/*.cpp" "src/*.hpp")
file(GLOB_RECURSE LIB_FILES CONFIGURE_DEPENDS "lib/*.cpp" "lib/*.h")
add_library(Flarial SHARED main.cpp ${SOURCE_FILES} ${LIB_FILES} src/Assets/Assets.rc
src/SDK/Client/Network/Packet/AnimatePacket.hpp
src/Client/Module/Modules/Subtitles/Subtitles.cpp
src/Client/Module/Modules/Subtitles/Subtitles.hpp
src/Client/Events/Game/SoundEnginePlayEvent.hpp
src/SDK/Client/Network/Packet/TakeItemActorPacket.hpp)

function(flarial_assign_unique_object_names target)
if (NOT MSVC)
return()
endif()

get_target_property(target_sources ${target} SOURCES)
if (NOT target_sources)
return()
endif()

set(compiled_sources)
foreach(source IN LISTS target_sources)
if (IS_ABSOLUTE "${source}")
set(source_path "${source}")
else()
set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/${source}")
endif()

get_filename_component(source_ext "${source_path}" EXT)
string(TOLOWER "${source_ext}" source_ext_lower)
if (NOT source_ext_lower STREQUAL ".c" AND
NOT source_ext_lower STREQUAL ".cc" AND
NOT source_ext_lower STREQUAL ".cxx" AND
NOT source_ext_lower STREQUAL ".cpp")
continue()
endif()

get_filename_component(source_name "${source_path}" NAME_WE)
string(TOLOWER "${source_name}" source_name_lower)
set(source_count_var "FLARIAL_SOURCE_BASENAME_COUNT_${source_name_lower}")
if (DEFINED ${source_count_var})
math(EXPR ${source_count_var} "${${source_count_var}} + 1")
else()
set(${source_count_var} 1)
endif()

list(APPEND compiled_sources "${source}")
endforeach()

foreach(source IN LISTS compiled_sources)
if (IS_ABSOLUTE "${source}")
set(source_path "${source}")
else()
set(source_path "${CMAKE_CURRENT_SOURCE_DIR}/${source}")
endif()

get_filename_component(source_name "${source_path}" NAME_WE)
string(TOLOWER "${source_name}" source_name_lower)
set(source_count_var "FLARIAL_SOURCE_BASENAME_COUNT_${source_name_lower}")
if (NOT ${${source_count_var}} GREATER 1)
continue()
endif()

file(RELATIVE_PATH rel_source_path "${CMAKE_CURRENT_SOURCE_DIR}" "${source_path}")
get_filename_component(rel_source_dir "${rel_source_path}" DIRECTORY)
set(unique_object_name "${rel_source_dir}_${source_name}")
string(REGEX REPLACE "[^A-Za-z0-9_]" "_" unique_object_name "${unique_object_name}")

# Visual Studio uses a flat object-output directory by default; duplicate
# basenames like Manager.cpp would otherwise collide under the same .obj path.
set_property(SOURCE "${source}" APPEND PROPERTY COMPILE_OPTIONS
"/Fo$(IntDir)${unique_object_name}.obj")
endforeach()
endfunction()

flarial_assign_unique_object_names(Flarial)

target_include_directories(Flarial PRIVATE
"."
"src"
Expand Down Expand Up @@ -114,11 +184,12 @@ set_target_properties(MinHook PROPERTIES IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE
add_library(FreeType SHARED IMPORTED GLOBAL)
set_target_properties(FreeType PROPERTIES IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/freetype/libs/freetype.lib")

add_library(libcurl SHARED IMPORTED GLOBAL)
add_library(libcurl STATIC IMPORTED GLOBAL)
set_target_properties(libcurl PROPERTIES
MSVC_RUNTIME_LIBRARY "MultiThreaded"
INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB"
IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/curl/libcurl.lib"
)
set_target_properties(libcurl PROPERTIES IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/curl/libcurl.lib")

add_library(zlib SHARED IMPORTED GLOBAL)
set_target_properties(zlib PROPERTIES
Expand All @@ -127,6 +198,7 @@ set_target_properties(zlib PROPERTIES
set_target_properties(zlib PROPERTIES IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/curl/zlib.lib")

include(FetchContent)
set(FETCHCONTENT_UPDATES_DISCONNECTED ON CACHE BOOL "" FORCE)

FetchContent_Declare(
entt
Expand All @@ -143,13 +215,13 @@ FetchContent_Declare(
FetchContent_Declare(
libhat
GIT_REPOSITORY https://github.com/BasedInc/libhat.git
GIT_TAG d6297514b05fd238f5b46d003325f108c22741e3
GIT_TAG v0.9.0
)

FetchContent_Declare(
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG master
GIT_TAG 12.1.0
)

FetchContent_Declare(
Expand Down Expand Up @@ -191,7 +263,11 @@ FetchContent_Declare(
set(FMT_MODULE OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(libhat entt nes fmt magic_enum LuaBridge safetyhook jsoncpp discord-rpc rift)

target_link_libraries(Flarial PRIVATE jsoncpp safetyhook libcurl ws2_32.lib crypt32.lib normaliz.lib wldap32.lib LuaBridge lua_static libhat fmt::fmt EnTT::EnTT NES windowscodecs.lib urlmon.lib dwrite.lib d3d12.lib dxgi.lib d3d11.lib d2d1.lib wininet.lib setupapi.lib version FreeType magic_enum runtimeobject discord-rpc rift)
target_link_libraries(Flarial PRIVATE jsoncpp safetyhook libcurl ws2_32.lib crypt32.lib normaliz.lib wldap32.lib bcrypt.lib secur32.lib iphlpapi.lib advapi32.lib LuaBridge lua_static libhat fmt::fmt EnTT::EnTT NES windowscodecs.lib urlmon.lib dwrite.lib d3d12.lib dxgi.lib d3d11.lib d2d1.lib wininet.lib setupapi.lib version FreeType magic_enum runtimeobject discord-rpc rift)

# curl 8.17 protocol-handler table is referenced only internally; without WHOLEARCHIVE,
# LTCG strips Curl_handler_http/https/ws/wss and curl_easy_perform returns CURLE_UNSUPPORTED_PROTOCOL.
target_link_options(Flarial PRIVATE "/WHOLEARCHIVE:libcurl.lib")

target_link_libraries(Flarial PUBLIC MinHook)

Expand Down
71 changes: 29 additions & 42 deletions src/Client/Hook/Hooks/Render/DirectX/DX11/SwapchainHook_DX11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,36 +192,42 @@ void SwapchainHook::_DX11RenderUnderUI()
if (ModuleManager::initialized) {
auto motionBlurModule = ModuleManager::getModule("Motion Blur");
auto depthOfFieldModule = ModuleManager::getModule("Depth Of Field");
auto fovChangerModule = ModuleManager::getModule("FOV Changer");

bool needsBuffer = FlarialGUI::inMenu;
if (motionBlurModule && motionBlurModule->isEnabled()) needsBuffer = true;
if (depthOfFieldModule && depthOfFieldModule->isEnabled()) needsBuffer = true;
if (fovChangerModule && fovChangerModule->isEnabled() && fovChangerModule->getOps<bool>("panini")) needsBuffer = true;

FlarialGUI::needsBackBuffer = needsBuffer;
}

SaveBackbuffer(true);

/*
static UINT lastBufferWidth = 0, lastBufferHeight = 0;
// Ensure cachedDX11RTV exists and matches the current backbuffer dimensions.
// This was previously commented out, causing event->RTV to be null on the
// first frame and after any resize — breaking all UnderUI post-process modules.
{
static UINT lastUnderUIWidth = 0, lastUnderUIHeight = 0;

winrt::com_ptr<ID3D11Texture2D> backBuffer;
if (FAILED(swapchain->GetBuffer(0, IID_PPV_ARGS(backBuffer.put())))) {
return;/
}
winrt::com_ptr<ID3D11Texture2D> backBuffer;
if (FAILED(swapchain->GetBuffer(0, IID_PPV_ARGS(backBuffer.put())))) {
return;
}

D3D11_TEXTURE2D_DESC desc;
backBuffer->GetDesc(&desc);
D3D11_TEXTURE2D_DESC desc;
backBuffer->GetDesc(&desc);

if (!cachedDX11RTV.get() || desc.Width != lastBufferWidth || desc.Height != lastBufferHeight) {
cachedDX11RTV = nullptr;
if (FAILED(d3d11Device->CreateRenderTargetView(backBuffer.get(), nullptr, cachedDX11RTV.put()))) {
return;
if (!cachedDX11RTV.get() || desc.Width != lastUnderUIWidth || desc.Height != lastUnderUIHeight) {
cachedDX11RTV = nullptr;
if (FAILED(d3d11Device->CreateRenderTargetView(backBuffer.get(), nullptr, cachedDX11RTV.put()))) {
return;
}
lastUnderUIWidth = desc.Width;
lastUnderUIHeight = desc.Height;
}
lastBufferWidth = desc.Width;
lastBufferHeight = desc.Height;
}
*/

winrt::com_ptr<ID3D11RenderTargetView> originalRTV[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
winrt::com_ptr<ID3D11DepthStencilView> originalDSV = nullptr;

Expand All @@ -235,37 +241,16 @@ void SwapchainHook::_DX11RenderUnderUI()
}
originalDSV.attach(dsv);


/*
D2D::context->BeginDraw();

ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();

ImGui::Begin("t", nullptr,
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground |
ImGuiWindowFlags_NoDecoration);

*/

auto event = nes::make_holder<RenderUnderUIEvent>();
event->RTV = cachedDX11RTV.get();
eventMgr.trigger(event);

/* At the moment, Flarial does not utilize ImGui under ui.
* Even if you uncomment the following lines, it won't work,
* Something special needs to be done.
D2D::context->EndDraw();

ImGui::End();
ImGui::EndFrame();
ImGui::Render();

ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
*/

// NOTE: ImGui is NOT available during RenderUnderUIEvent.
// Modules that need to render here must use raw D3D11 draw calls
// (like RealMotionBlurHelper, DepthOfFieldHelper, PaniniProjectionHelper).
// ImGui-based rendering (e.g. MotionBlur's ImageWithOpacity for Average/Ghost/V4
// blur types) will silently do nothing because there is no active ImGui frame.
// Starting an ImGui frame here would conflict with the one in _DX11Render().

ID3D11RenderTargetView* restoreRTVs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {};
for (UINT i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) {
Expand All @@ -287,10 +272,12 @@ void SwapchainHook::DX11Blur() {
if (ModuleManager::initialized) {
auto motionBlurModule = ModuleManager::getModule("Motion Blur");
auto depthOfFieldModule = ModuleManager::getModule("Depth Of Field");
auto fovChangerModule = ModuleManager::getModule("FOV Changer");

bool needsBuffer = FlarialGUI::inMenu;
if (motionBlurModule && motionBlurModule->isEnabled()) needsBuffer = true;
if (depthOfFieldModule && depthOfFieldModule->isEnabled()) needsBuffer = true;
if (fovChangerModule && fovChangerModule->isEnabled() && fovChangerModule->getOps<bool>("panini")) needsBuffer = true;

FlarialGUI::needsBackBuffer = needsBuffer;
}
Expand Down
13 changes: 11 additions & 2 deletions src/Client/Hook/Hooks/Render/DirectX/DX12/SwapchainHook_DX12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,17 @@ void SwapchainHook::DX12Blur() {

/* Blur Stuff */
prepareBlur();
if (FlarialGUI::inMenu) FlarialGUI::needsBackBuffer = true;
else FlarialGUI::needsBackBuffer = false;
bool needsBuffer = FlarialGUI::inMenu;
if (ModuleManager::initialized) {
auto motionBlurModule = ModuleManager::getModule("Motion Blur");
auto depthOfFieldModule = ModuleManager::getModule("Depth Of Field");
auto fovChangerModule = ModuleManager::getModule("FOV Changer");

if (motionBlurModule && motionBlurModule->isEnabled()) needsBuffer = true;
if (depthOfFieldModule && depthOfFieldModule->isEnabled()) needsBuffer = true;
if (fovChangerModule && fovChangerModule->isEnabled() && fovChangerModule->getOps<bool>("panini")) needsBuffer = true;
}
FlarialGUI::needsBackBuffer = needsBuffer;
/* Blur End */

}
Expand Down
20 changes: 6 additions & 14 deletions src/Client/Hook/Hooks/Render/DirectX/DXGI/UnderUIHooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,10 @@ void UnderUIHooks::ClearDepthStencilViewCallbackDX12(
UINT NumRects,
const D3D12_RECT *pRects) {


index++;

if (ClearFlags == D3D12_CLEAR_FLAG_DEPTH && SwapchainHook::init){
if (ClearFlags == D3D12_CLEAR_FLAG_DEPTH && SwapchainHook::init) {
savedpDethStencilView = pDepthStencilView;
SwapchainHook::DX12Render(true);
}
funcOriginalDX12(cmdList, pDepthStencilView, ClearFlags, Depth, Stencil, NumRects, pRects);

Expand Down Expand Up @@ -201,17 +199,11 @@ void UnderUIHooks::enableHook() {

} else {

/* DX12 */

/*
void** vtable = *reinterpret_cast<void***>(SwapchainHook::DX12CommandLists);
const size_t INDEX_CLEAR_DEPTH_STENCIL_VIEW = 47;
Memory::hookFunc(
vtable[INDEX_CLEAR_DEPTH_STENCIL_VIEW],
ClearDepthStencilViewCallbackDX12,
(void**)&funcOriginalDX12,
"ClearDepthStencilViewDX12"
);*/
/* DX12 — ClearDepthStencilView hook is not viable mid-frame on DX12.
* D3D11On12 AcquireWrappedResources + ReleaseWrappedResources transitions
* the backbuffer state, and restoring it requires fence waits that stall
* the GPU pipeline and risk heap corruption on resize/fullscreen.
* RenderUnderUIEvent is DX11-only; DX12 modules fall back to RenderEvent. */

/* DX12 */

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,8 @@ void DepthOfFieldHelper::RenderDepthOfField(ID3D11RenderTargetView* pDstRenderTa
auto backbuffer = SwapchainHook::GetBackbuffer();
if (intensity <= 0 || !backbuffer || !pDepthMapSRV) return;

winrt::com_ptr<ID3D11ShaderResourceView> pOrigShaderResourceView = MotionBlur::BackbufferToSRVExtraMode();
// DepthOfField renders during RenderUnderUIEvent, so read from the underUI backbuffer pool
winrt::com_ptr<ID3D11ShaderResourceView> pOrigShaderResourceView = MotionBlur::BackbufferToSRVExtraMode(true);
if (!pOrigShaderResourceView) return;

winrt::com_ptr<ID3D11DeviceContext> pContext = SwapchainHook::context;
Expand Down
Loading
Loading