diff --git a/Assets/Common/AddressRecords.json b/Assets/Common/AddressRecords.json
index bd11e23..9324e9a 100644
--- a/Assets/Common/AddressRecords.json
+++ b/Assets/Common/AddressRecords.json
@@ -434,6 +434,11 @@
"Pattern": "48 8b 81 70 02 00 00 48 8b f2 48 8b d9 48 3b c2 74 1e",
"Offset": -15
},
+ {
+ "Name": "sMhRender:Assignment",
+ "Pattern": "89 44 24 20 E8 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? C7 83 ?? ?? ?? ?? 06 00 00 00 48 89 03",
+ "Offset": 9
+ },
{
"Name": "D3DRender12:SwapChainPresentCall",
"Pattern": "FF 50 40 C6 83 D9 10 00 00 01 85 C0 75 1A 41 FF C4 44 8D 78 01",
diff --git a/SharpPluginLoader.Core/IPlugin.cs b/SharpPluginLoader.Core/IPlugin.cs
index 0b29c47..a56eed3 100644
--- a/SharpPluginLoader.Core/IPlugin.cs
+++ b/SharpPluginLoader.Core/IPlugin.cs
@@ -11,6 +11,22 @@ namespace SharpPluginLoader.Core
#pragma warning disable CS0649
+ public enum ShaderSourceType : int {
+ HLSL = 0,
+ BINARY
+ };
+
+ unsafe public struct ShaderReplacement {
+ public ShaderSourceType Type;
+ public byte* Source;
+ public int Length;
+ };
+
+ unsafe public struct ShaderInfo {
+ public fixed sbyte DxbcHash[36];
+ public ShaderReplacement Replacement;
+ };
+
///
/// Contains some configuration data for a plugin. This is returned by .
///
@@ -37,6 +53,9 @@ public class PluginData
///
internal bool OnResourceLoad;
+ ///
+ internal bool OnCreateShader;
+
///
internal bool OnChatMessageSent;
#endregion
@@ -52,7 +71,7 @@ public class PluginData
internal bool OnQuestDepart;
///
- internal bool OnQuestEnter;
+ internal bool OnQuestEnter;
///
internal bool OnQuestLeave;
@@ -107,7 +126,7 @@ public class PluginData
#region Entity
///
internal bool OnEntityAction;
-
+
///
internal bool OnEntityAnimation;
@@ -159,7 +178,7 @@ public interface IPlugin
///
/// Gets called when the plugin is loaded. This is where you can optionally configure your plugin within the framework.
- ///
+ ///
/// Default event, always called once per plugin [re]load.
///
/// The filled out PluginData
@@ -168,7 +187,7 @@ public interface IPlugin
///
/// Gets called after the game has initialized it's singletons. This is you initialize anything in your plugin
/// that uses the game state (e.g. reading pointers, accessing singletons, etc).
- ///
+ ///
/// Default event, always called once per plugin [re]load.
///
public void OnLoad() { } // Not marked as a plugin event because it's always called
@@ -237,6 +256,13 @@ public void OnUnload() { }
[PluginEvent]
public void OnResourceLoad(Resource? resource, MtDti dti, string path, LoadFlags flags) => throw new NotImplementedException();
+ ///
+ /// Gets called when the game creates a new shader.
+ ///
+ /// Metadata and fields to optionally define a replacement shader
+ [PluginEvent]
+ public unsafe void OnCreateShader(ShaderInfo* info) => throw new NotImplementedException();
+
///
/// Gets called when a chat message is sent (on the local side).
///
diff --git a/SharpPluginLoader.Core/Rendering/Renderer.cs b/SharpPluginLoader.Core/Rendering/Renderer.cs
index 4e8d2f6..d1c5675 100644
--- a/SharpPluginLoader.Core/Rendering/Renderer.cs
+++ b/SharpPluginLoader.Core/Rendering/Renderer.cs
@@ -466,6 +466,13 @@ ref MemoryUtil.AsRef(_renderingOptionPointers.LineThickness),
return (nint)ImGui.GetDrawData().NativePtr;
}
+ [UnmanagedCallersOnly]
+ internal static unsafe void CreateShader(ShaderInfo* info)
+ {
+ foreach (var plugin in PluginManager.Instance.GetPlugins(p => p.OnCreateShader))
+ plugin.OnCreateShader(info);
+ }
+
internal static void Shutdown()
{
ImGui.DestroyContext();
diff --git a/mhw-cs-plugin-loader/D3DModule.cpp b/mhw-cs-plugin-loader/D3DModule.cpp
index e88ad29..6ea4f29 100644
--- a/mhw-cs-plugin-loader/D3DModule.cpp
+++ b/mhw-cs-plugin-loader/D3DModule.cpp
@@ -1,6 +1,8 @@
#include "D3DModule.h"
+#include
#include
+#include
#include "CoreClr.h"
#include "Config.h"
@@ -14,9 +16,6 @@
#include "imgui_impl_dx11.h"
#include "imgui_impl_win32.h"
-#include
-#include
-
#include "ChunkModule.h"
#include "HResultHandler.h"
#include "LoaderConfig.h"
@@ -39,11 +38,16 @@ void D3DModule::initialize(CoreClr* coreclr) {
L"SharpPluginLoader.Core.Rendering.Renderer",
L"Render"
);
- m_core_imgui_render = coreclr->get_method(
+ m_core_imgui_render = coreclr->get_method(
config::SPL_CORE_ASSEMBLY_NAME,
L"SharpPluginLoader.Core.Rendering.Renderer",
L"ImGuiRender"
);
+ m_core_create_shader = coreclr->get_method(
+ config::SPL_CORE_ASSEMBLY_NAME,
+ L"SharpPluginLoader.Core.Rendering.Renderer",
+ L"CreateShader"
+ );
m_core_initialize_imgui = coreclr->get_method(
config::SPL_CORE_ASSEMBLY_NAME,
L"SharpPluginLoader.Core.Rendering.Renderer",
@@ -65,8 +69,11 @@ void D3DModule::initialize(CoreClr* coreclr) {
L"GetSingletonNative"
);
- const auto play = (void*)NativePluginFramework::get_repository_address("GUITitle:Play");
- m_title_menu_ready_hook = safetyhook::create_inline(play, title_menu_ready_hook);
+ const auto render_assignment = (void*)NativePluginFramework::get_repository_address("sMhRender:Assignment");
+ m_create_renderer_hook = safetyhook::create_mid(render_assignment, [](safetyhook::Context& ctx) {
+ const auto self = NativePluginFramework::get_module();
+ self->common_initialize(ctx.rax);
+ });
coreclr->add_internal_call("LoadTexture", (void*)load_texture);
coreclr->add_internal_call("UnloadTexture", (void*)unload_texture);
@@ -77,12 +84,11 @@ void D3DModule::shutdown() {
m_d3d_present_hook.reset();
if (m_is_d3d12) {
- m_d3d_execute_command_lists_hook.reset();
m_d3d_signal_hook.reset();
}
}
-void D3DModule::common_initialize() {
+void D3DModule::common_initialize(const uintptr_t render_singleton) {
const uintptr_t callIsD3D12 = PatternScanner::find_first(
Pattern::from_string("05 7D 14 00 4C 8B 8D D8 08 00 00 84 C0 0F B6 85 F0 08 00 00")
);
@@ -91,8 +97,6 @@ void D3DModule::common_initialize() {
m_is_d3d12 = isD3D12();
dlog::debug("Found cD3DRender::isD3D12 at {:p}", (void*)isD3D12);
- m_title_menu_ready_hook.reset();
-
dlog::debug("Initializing D3D module for {}", m_is_d3d12 ? "D3D12" : "D3D11");
const auto game_window_name = std::format("MONSTER HUNTER: WORLD({})", NativePluginFramework::get_game_revision());
@@ -130,7 +134,7 @@ void D3DModule::common_initialize() {
TEXT("SharpPluginLoader DX Hook"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
- 100, 100,
+ 0, 0,
nullptr,
nullptr,
window_class->hInstance,
@@ -142,336 +146,65 @@ void D3DModule::common_initialize() {
return;
}
+ const auto renderer = *(uintptr_t*)(render_singleton + 0x78);
if (m_is_d3d12) {
- initialize_for_d3d12_alt();
+ initialize_for_d3d12(renderer);
} else {
- initialize_for_d3d11_alt();
+ initialize_for_d3d11(renderer);
}
DestroyWindow(m_temp_window);
UnregisterClass(window_class->lpszClassName, window_class->hInstance);
}
-void D3DModule::initialize_for_d3d12() {
- HMODULE dxgi;
-
- if ((dxgi = GetModuleHandleA("dxgi.dll")) == nullptr) {
- dlog::error("Failed to find dxgi.dll");
- return;
- }
-
- if ((m_d3d12_module = GetModuleHandleA("d3d12.dll")) == nullptr) {
- dlog::error("Failed to find d3d12.dll");
- return;
- }
-
- decltype(CreateDXGIFactory)* create_dxgi_factory;
- if ((create_dxgi_factory = (decltype(create_dxgi_factory))GetProcAddress(dxgi, "CreateDXGIFactory")) == nullptr) {
- dlog::error("Failed to find CreateDXGIFactory");
- return;
- }
-
- IDXGIFactory* factory;
- if (FAILED(create_dxgi_factory(IID_PPV_ARGS(&factory)))) {
- dlog::error("Failed to create DXGI factory");
- return;
- }
-
- IDXGIAdapter* adapter;
- if (FAILED(factory->EnumAdapters(0, &adapter))) {
- dlog::error("Failed to enumerate DXGI adapters");
- return;
- }
-
- decltype(D3D12CreateDevice)* d3d12_create_device;
- if ((d3d12_create_device = (decltype(d3d12_create_device))GetProcAddress(m_d3d12_module, "D3D12CreateDevice")) == nullptr) {
- dlog::error("Failed to find D3D12CreateDevice");
- return;
- }
-
- ID3D12Device* device;
- if (FAILED(d3d12_create_device(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device)))) {
- dlog::error("Failed to create D3D12 device");
- return;
- }
-
- constexpr D3D12_COMMAND_QUEUE_DESC queue_desc = {
- .Type = D3D12_COMMAND_LIST_TYPE_DIRECT,
- .Priority = 0,
- .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
- .NodeMask = 0
- };
-
- ID3D12CommandQueue* command_queue;
- if (FAILED(device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&command_queue)))) {
- dlog::error("Failed to create D3D12 command queue");
- return;
- }
-
- ID3D12CommandAllocator* command_allocator;
- if (FAILED(device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&command_allocator)))) {
- dlog::error("Failed to create D3D12 command allocator");
- return;
- }
-
- ID3D12CommandList* command_list;
- if (FAILED(device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, command_allocator, nullptr, IID_PPV_ARGS(&command_list)))) {
- dlog::error("Failed to create D3D12 command list");
- return;
- }
-
- constexpr DXGI_RATIONAL refresh_rate = {
- .Numerator = 60,
- .Denominator = 1
- };
-
- DXGI_MODE_DESC buffer_desc = {
- .Width = 100,
- .Height = 100,
- .RefreshRate = refresh_rate,
- .Format = DXGI_FORMAT_R8G8B8A8_UNORM,
- .ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
- .Scaling = DXGI_MODE_SCALING_UNSPECIFIED
- };
-
- constexpr DXGI_SAMPLE_DESC sample_desc = {
- .Count = 1,
- .Quality = 0
- };
-
- DXGI_SWAP_CHAIN_DESC sd = {
- .BufferDesc = buffer_desc,
- .SampleDesc = sample_desc,
- .BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
- .BufferCount = 2,
- .OutputWindow = m_temp_window,
- .Windowed = TRUE,
- .SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD,
- .Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
- };
-
- IDXGISwapChain* swap_chain;
- if (FAILED(factory->CreateSwapChain(command_queue, &sd, &swap_chain))) {
- dlog::error("Failed to create DXGI swap chain");
- return;
- }
-
- // SwapChainVFT[8]: Present
- // SwapChainVFT[13]: ResizeBuffers
- // CommandQueueVFT[10]: ExecuteCommandLists
- // CommandQueueVFT[14]: Signal
-
- const auto swap_chain_vft = *(void***)swap_chain;
- const auto command_queue_vft = *(void***)command_queue;
-
- const auto present = swap_chain_vft[8];
- const auto resize_buffers = swap_chain_vft[13];
- const auto execute_command_lists = command_queue_vft[10];
- const auto signal = command_queue_vft[14];
-
- m_d3d_present_hook = safetyhook::create_inline(present, d3d12_present_hook);
- m_d3d_execute_command_lists_hook = safetyhook::create_inline(execute_command_lists, d3d12_execute_command_lists_hook);
- m_d3d_signal_hook = safetyhook::create_inline(signal, d3d12_signal_hook);
- m_d3d_resize_buffers_hook = safetyhook::create_inline(resize_buffers, d3d_resize_buffers_hook);
-
- device->Release();
- command_queue->Release();
- command_allocator->Release();
- command_list->Release();
- swap_chain->Release();
- factory->Release();
-}
-
-void D3DModule::initialize_for_d3d11() {
- if ((m_d3d11_module = GetModuleHandleA("d3d11.dll")) == nullptr) {
- dlog::error("Failed to find d3d11.dll");
- return;
- }
-
- decltype(D3D11CreateDeviceAndSwapChain)* d3d11_create_device_and_swap_chain;
- if ((d3d11_create_device_and_swap_chain = (decltype(d3d11_create_device_and_swap_chain))GetProcAddress(m_d3d11_module, "D3D11CreateDeviceAndSwapChain")) == nullptr) {
- dlog::error("Failed to find D3D11CreateDeviceAndSwapChain");
- return;
- }
-
- constexpr D3D_FEATURE_LEVEL feature_levels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1 };
- D3D_FEATURE_LEVEL feature_level;
-
- constexpr DXGI_RATIONAL refresh_rate = {
- .Numerator = 60,
- .Denominator = 1
- };
-
- constexpr DXGI_MODE_DESC buffer_desc = {
- .Width = 100,
- .Height = 100,
- .RefreshRate = refresh_rate,
- .Format = DXGI_FORMAT_R8G8B8A8_UNORM,
- .ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
- .Scaling = DXGI_MODE_SCALING_UNSPECIFIED
- };
-
- constexpr DXGI_SAMPLE_DESC sample_desc = {
- .Count = 1,
- .Quality = 0
- };
-
- DXGI_SWAP_CHAIN_DESC sd = {
- .BufferDesc = buffer_desc,
- .SampleDesc = sample_desc,
- .BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
- .BufferCount = 1,
- .OutputWindow = m_temp_window,
- .Windowed = TRUE,
- .SwapEffect = DXGI_SWAP_EFFECT_DISCARD,
- .Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
- };
-
- IDXGISwapChain* swap_chain;
- ID3D11Device* device;
- ID3D11DeviceContext* device_context;
-
- if (FAILED(d3d11_create_device_and_swap_chain(
- nullptr,
- D3D_DRIVER_TYPE_HARDWARE,
- nullptr, 0,
- feature_levels,
- _countof(feature_levels),
- D3D11_SDK_VERSION,
- &sd, &swap_chain, &device, &feature_level, &device_context))) {
- dlog::error("Failed to create D3D11 device and swap chain");
- return;
- }
-
- // SwapChainVFT[8]: Present
- const auto swap_chain_vft = *(void***)swap_chain;
- const auto present = swap_chain_vft[8];
-
- m_d3d_present_hook = safetyhook::create_inline(present, d3d11_present_hook);
-}
-
-void D3DModule::initialize_for_d3d12_alt() {
- const auto present_call = NativePluginFramework::get_repository_address("D3DRender12:SwapChainPresentCall");
- if (!present_call) {
- dlog::error("Failed to find SwapChainPresentCall");
- return;
- }
-
- if ((m_d3d12_module = GetModuleHandleA("d3d12.dll")) == nullptr) {
- dlog::error("Failed to find d3d12.dll");
+void D3DModule::initialize_for_d3d12(const uintptr_t renderer) {
+ const auto swap_chain = *(IDXGISwapChain**)(renderer + 0x1470);
+ m_d3d12_command_queue = *(ID3D12CommandQueue**)(renderer + 0x20);
+ dlog::debug("D3D12 Command Queue found at {:p}", (void*)m_d3d12_command_queue);
+ if (FAILED(swap_chain->GetDevice(IID_PPV_ARGS(&m_d3d12_device)))) {
+ dlog::error("Failed to get D3D12 device during initialization");
return;
}
- m_d3d_present_hook_alt = safetyhook::create_mid(present_call, [](safetyhook::Context& ctx) {
- const auto self = NativePluginFramework::get_module();
- const auto prm = NativePluginFramework::get_module();
- const auto& config = preloader::LoaderConfig::get();
-
- const auto swap_chain = (IDXGISwapChain*)ctx.rcx;
-
- if (self->m_is_inside_present) {
- return;
- }
-
- self->m_is_inside_present = true;
-
- if (!self->m_is_initialized) {
- self->d3d12_initialize_imgui(swap_chain);
-
- if (!self->m_texture_manager) {
- self->m_texture_manager = std::make_unique(
- self->m_d3d12_device,
- self->m_d3d12_command_queue,
- self->m_d3d12_srv_heap
- );
- }
-
- if (config.get_primitive_rendering_enabled()) {
- prm->late_init(self.get(), swap_chain);
- }
- }
-
- if (!self->m_d3d12_command_queue) {
- self->m_is_inside_present = false;
- return;
- }
-
- const auto facility = (uintptr_t)self->m_get_singleton("sFacility");
-
- // Check if Steamworks is active. This is a very hacky fix for the AutoSteamworks app,
- // which sometimes sends invalid input events that trip up ImGui.
- // So we just disable ImGui rendering when Steamworks is active. Ideally we should
- // check if the app is even running, but whatever. This is (probably) a temporary fix.
- // +0x348 is the offset to cSteamControl, +0x444 is the offset from that to the mState field.
- if (facility && *(u32*)(facility + 0x348 + 0x444) > 5) {
- self->m_is_inside_present = false;
- return;
- }
-
- self->d3d12_present_hook_core(swap_chain, prm);
- self->m_is_inside_present = false;
- });
-
- const auto render_singleton = (uintptr_t)m_get_singleton("sMhRender");
- const auto renderer = *(uintptr_t*)(render_singleton + 0x78);
-
- m_d3d12_command_queue = *(ID3D12CommandQueue**)(renderer + 0x20);
- const auto swap_chain = *(IDXGISwapChain3**)(renderer + 0x1470);
const auto swap_chain_vft = *(void***)swap_chain;
const auto cmd_queue_vft = *(void***)m_d3d12_command_queue;
+ const auto device_vft = *(void***)m_d3d12_device;
+ const auto present = swap_chain_vft[8];
const auto resize_buffers = swap_chain_vft[13];
const auto signal = cmd_queue_vft[14];
+ const auto create_graphics_pipeline_state = device_vft[10];
+ const auto create_compute_pipeline_state = device_vft[11];
- dlog::debug("D3D12 Command Queue found at {:p}", (void*)m_d3d12_command_queue);
-
+ m_d3d_present_hook = safetyhook::create_inline(present, d3d12_present_hook);
m_d3d_resize_buffers_hook = safetyhook::create_inline(resize_buffers, d3d_resize_buffers_hook);
m_d3d_signal_hook = safetyhook::create_inline(signal, d3d12_signal_hook);
+ m_d3d_create_graphics_pipeline_hook = safetyhook::create_inline(create_graphics_pipeline_state, d3d12_create_graphics_pipeline_state_hook);
+ m_d3d_create_compute_pipeline_hook = safetyhook::create_inline(create_compute_pipeline_state, d3d12_create_compute_pipeline_state_hook);
}
-void D3DModule::initialize_for_d3d11_alt() {
- const auto present_call = NativePluginFramework::get_repository_address("D3DRender11:SwapChainPresentCall");
- if (!present_call) {
- dlog::error("Failed to find SwapChainPresentCall");
+void D3DModule::initialize_for_d3d11(const uintptr_t renderer) {
+ const auto swap_chain = *(IDXGISwapChain**)(renderer + 0x1488);
+ if (FAILED(swap_chain->GetDevice(IID_PPV_ARGS(&m_d3d11_device)))) {
+ dlog::error("Failed to get D3D11 device during initialization");
return;
}
- m_d3d_present_hook_alt = safetyhook::create_mid(present_call, [](safetyhook::Context& ctx) {
- const auto self = NativePluginFramework::get_module();
- const auto prm = NativePluginFramework::get_module();
- const auto& config = preloader::LoaderConfig::get();
-
- const auto swap_chain = (IDXGISwapChain*)ctx.rcx;
-
- if (self->m_is_inside_present) {
- return;
- }
-
- self->m_is_inside_present = true;
-
- if (!self->m_is_initialized) {
- self->d3d11_initialize_imgui(swap_chain);
-
- if (!self->m_texture_manager) {
- self->m_texture_manager = std::make_unique(self->m_d3d11_device, self->m_d3d11_device_context);
- }
+ const auto swap_chain_vft = *(void***)swap_chain;
+ const auto device_vft = *(void***)m_d3d11_device;
- if (config.get_primitive_rendering_enabled()) {
- prm->late_init(self.get(), swap_chain);
- }
- }
+ const auto present = swap_chain_vft[8];
+ const auto create_vertex_shader = device_vft[12];
+ const auto create_pixel_shader = device_vft[15];
+ const auto create_compute_shader = device_vft[18];
- self->d3d11_present_hook_core(swap_chain, prm);
- self->m_is_inside_present = false;
- });
+ m_d3d_present_hook = safetyhook::create_inline(present, d3d11_present_hook);
+ m_d3d_create_vertex_shader_hook = safetyhook::create_inline(create_vertex_shader, d3d11_create_vertex_shader_hook);
+ m_d3d_create_pixel_shader_hook = safetyhook::create_inline(create_pixel_shader, d3d11_create_pixel_shader_hook);
+ m_d3d_create_compute_shader_hook = safetyhook::create_inline(create_compute_shader, d3d11_create_compute_shader_hook);
}
void D3DModule::d3d12_initialize_imgui(IDXGISwapChain* swap_chain) {
- if (FAILED(swap_chain->GetDevice(IID_PPV_ARGS(&m_d3d12_device)))) {
- dlog::error("Failed to get D3D12 device in present hook");
- return;
- }
-
DXGI_SWAP_CHAIN_DESC desc;
if (FAILED(swap_chain->GetDesc(&desc))) {
dlog::error("Failed to get DXGI swap chain description");
@@ -482,11 +215,11 @@ void D3DModule::d3d12_initialize_imgui(IDXGISwapChain* swap_chain) {
GetClientRect(desc.OutputWindow, &client_rect);
const MtSize viewport_size = { desc.BufferDesc.Width, desc.BufferDesc.Height };
- const MtSize window_size = {
- (u32)(client_rect.right - client_rect.left),
- (u32)(client_rect.bottom - client_rect.top)
+ const MtSize window_size = {
+ (u32)(client_rect.right - client_rect.left),
+ (u32)(client_rect.bottom - client_rect.top)
};
-
+
const auto& config = preloader::LoaderConfig::get();
const auto context = m_core_initialize_imgui(viewport_size, window_size, true, config.get_menu_key().c_str());
@@ -525,7 +258,7 @@ void D3DModule::d3d12_initialize_imgui(IDXGISwapChain* swap_chain) {
m_d3d12_frame_contexts[i].CommandAllocator = command_allocator;
}
- if (FAILED(m_d3d12_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
+ if (FAILED(m_d3d12_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT,
command_allocator.Get(), nullptr, IID_PPV_ARGS(m_d3d12_command_list.GetAddressOf())))) {
dlog::error("Failed to create D3D12 command list");
return;
@@ -560,7 +293,7 @@ void D3DModule::d3d12_initialize_imgui(IDXGISwapChain* swap_chain) {
const auto buffer_desc = back_buffer->GetDesc();
dlog::debug("Creating RTV for back buffer {}, with size {}x{}", i, buffer_desc.Width, buffer_desc.Height);
-
+
m_d3d12_device->CreateRenderTargetView(back_buffer.Get(), nullptr, rtv_handle);
m_d3d12_frame_contexts[i].RenderTargetDescriptor = rtv_handle;
m_d3d12_frame_contexts[i].RenderTarget = back_buffer;
@@ -598,11 +331,6 @@ void D3DModule::d3d12_initialize_imgui(IDXGISwapChain* swap_chain) {
}
void D3DModule::d3d11_initialize_imgui(IDXGISwapChain* swap_chain) {
- if (FAILED(swap_chain->GetDevice(IID_PPV_ARGS(&m_d3d11_device)))) {
- dlog::error("Failed to get D3D11 device in present hook");
- return;
- }
-
m_d3d11_device->GetImmediateContext(&m_d3d11_device_context);
DXGI_SWAP_CHAIN_DESC desc;
@@ -615,9 +343,9 @@ void D3DModule::d3d11_initialize_imgui(IDXGISwapChain* swap_chain) {
GetClientRect(desc.OutputWindow, &client_rect);
const MtSize viewport_size = { desc.BufferDesc.Width, desc.BufferDesc.Height };
- const MtSize window_size = {
- (u32)(client_rect.right - client_rect.left),
- (u32)(client_rect.bottom - client_rect.top)
+ const MtSize window_size = {
+ (u32)(client_rect.right - client_rect.left),
+ (u32)(client_rect.bottom - client_rect.top)
};
const auto& config = preloader::LoaderConfig::get();
@@ -747,66 +475,48 @@ bool D3DModule::is_d3d12() {
return m_is_d3d12;
}
-void D3DModule::title_menu_ready_hook(void* gui) {
- const auto self = NativePluginFramework::get_module();
-
- std::thread t(&D3DModule::common_initialize, self);
- self->m_title_menu_ready_hook.call(gui);
- t.join();
-
- self->m_title_menu_ready_hook = {};
-}
-
-template
-auto invoke_if(const std::optional>& opt, F func, Args&&... args) {
- return opt.and_then(std::bind(func, std::forward(args)...));
-}
+/*
+ uintptr_t facility = 0;
+ // Check if Steamworks is active. This is a very hacky fix for the AutoSteamworks app,
+ // which sometimes sends invalid input events that trip up ImGui.
+ // So we just disable ImGui rendering when Steamworks is active. Ideally we should
+ // check if the app is even running, but whatever. This is (probably) a temporary fix.
+ // +0x348 is the offset to cSteamControl, +0x444 is the offset from that to the mState field.
+ facility = (uintptr_t)self->m_get_singleton("sFacility");
+ if (facility && *(u32*)(facility + 0x348 + 0x444) > 5) {
+ }
+*/
HRESULT D3DModule::d3d12_present_hook(IDXGISwapChain* swap_chain, UINT sync_interval, UINT flags) {
const auto self = NativePluginFramework::get_module();
const auto prm = NativePluginFramework::get_module();
const auto& config = preloader::LoaderConfig::get();
- if (self->m_is_inside_present) {
- return self->m_d3d_present_hook.call(swap_chain, sync_interval, flags);
- }
-
- self->m_is_inside_present = true;
-
- if (!self->m_is_initialized) {
- self->d3d12_initialize_imgui(swap_chain);
-
- if (!self->m_texture_manager) {
- self->m_texture_manager = std::make_unique(
- self->m_d3d12_device,
- self->m_d3d12_command_queue,
- self->m_d3d12_srv_heap
- );
- }
+ if (!self->m_is_inside_present) {
+ self->m_is_inside_present = true;
- if (config.get_primitive_rendering_enabled()) {
- prm->late_init(self.get(), swap_chain);
- }
- }
+ if (!self->m_is_initialized) {
+ self->d3d12_initialize_imgui(swap_chain);
- if (!self->m_d3d12_command_queue) {
- return self->m_d3d_present_hook.call(swap_chain, sync_interval, flags);
- }
+ if (!self->m_texture_manager) {
+ self->m_texture_manager = std::make_unique(
+ self->m_d3d12_device,
+ self->m_d3d12_command_queue,
+ self->m_d3d12_srv_heap
+ );
+ }
- const auto facility = (uintptr_t)self->m_get_singleton("sFacility");
+ if (config.get_primitive_rendering_enabled()) {
+ prm->late_init(self.get(), swap_chain);
+ }
+ }
- // Check if Steamworks is active. This is a very hacky fix for the AutoSteamworks app,
- // which sometimes sends invalid input events that trip up ImGui.
- // So we just disable ImGui rendering when Steamworks is active. Ideally we should
- // check if the app is even running, but whatever. This is (probably) a temporary fix.
- // +0x348 is the offset to cSteamControl, +0x444 is the offset from that to the mState field.
- if (facility && *(u32*)(facility + 0x348 + 0x444) > 5) {
- return self->m_d3d_present_hook.call(swap_chain, sync_interval, flags);
+ if (self->m_d3d12_command_queue) {
+ self->d3d12_present_hook_core(swap_chain, prm);
+ }
}
- self->d3d12_present_hook_core(swap_chain, prm);
-
- const HRESULT result = self->m_d3d_present_hook.call(swap_chain, sync_interval, flags);
+ HRESULT result = self->m_d3d_present_hook.call(swap_chain, sync_interval, flags);
self->m_is_inside_present = false;
return result;
@@ -856,26 +566,30 @@ void D3DModule::d3d12_present_hook_core(IDXGISwapChain* swap_chain, const std::s
m_d3d12_command_queue->ExecuteCommandLists(1, (ID3D12CommandList* const*)m_d3d12_command_list.GetAddressOf());
- if (igGetIO()->ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
- {
+ if (igGetIO()->ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
igUpdatePlatformWindows();
igRenderPlatformWindowsDefault(nullptr, m_d3d12_command_list.Get());
}
}
-void D3DModule::d3d12_execute_command_lists_hook(ID3D12CommandQueue* command_queue, UINT num_command_lists, ID3D12CommandList* const* command_lists) {
+HRESULT D3DModule::d3d_resize_buffers_hook(IDXGISwapChain* swap_chain, UINT buffer_count, UINT w, UINT h, DXGI_FORMAT format, UINT flags) {
const auto self = NativePluginFramework::get_module();
+ const auto prm = NativePluginFramework::get_module();
- if (!self->m_d3d12_command_queue && command_queue->GetDesc().Type == D3D12_COMMAND_LIST_TYPE_DIRECT) {
- dlog::debug("Found D3D12 command queue");
- self->m_d3d12_command_queue = command_queue;
+ dlog::debug("ResizeBuffers called, resetting...");
- if (self->m_texture_manager) {
- self->m_texture_manager->update_command_queue(command_queue);
+ if (self->m_is_initialized) {
+ self->m_is_initialized = false;
+ if (self->m_is_d3d12) {
+ self->d3d12_deinitialize_imgui();
+ } else {
+ self->d3d11_deinitialize_imgui();
}
}
- return self->m_d3d_execute_command_lists_hook.call(command_queue, num_command_lists, command_lists);
+ prm->shutdown();
+
+ return self->m_d3d_resize_buffers_hook.call(swap_chain, buffer_count, w, h, format, flags);
}
UINT64 D3DModule::d3d12_signal_hook(ID3D12CommandQueue* command_queue, ID3D12Fence* fence, UINT64 value) {
@@ -889,25 +603,82 @@ UINT64 D3DModule::d3d12_signal_hook(ID3D12CommandQueue* command_queue, ID3D12Fen
return self->m_d3d_signal_hook.call(command_queue, fence, value);
}
-HRESULT D3DModule::d3d_resize_buffers_hook(IDXGISwapChain* swap_chain, UINT buffer_count, UINT w, UINT h, DXGI_FORMAT format, UINT flags) {
- const auto self = NativePluginFramework::get_module();
- const auto prm = NativePluginFramework::get_module();
-
- dlog::debug("ResizeBuffers called, resetting...");
+bool D3DModule::compile_replacement_shader(ShaderReplacement& re, const char* target, D3D12_SHADER_BYTECODE* out) {
+ ID3DBlob* blob = nullptr;
+ HRESULT hr = D3DCompile(
+ re.Source,
+ re.Length,
+ nullptr,
+ nullptr,
+ nullptr,
+ "main",
+ target,
+ 0,
+ 0,
+ &blob,
+ nullptr
+ );
+ if (FAILED(hr)) {
+ dlog::error("Failed to compile replacement shader");
+ return false;
+ }
+ *out = CD3DX12_SHADER_BYTECODE(blob);
+ return true;
+}
- if (self->m_is_initialized) {
- self->m_is_initialized = false;
- if (self->m_is_d3d12) {
- self->d3d12_deinitialize_imgui();
+HRESULT D3DModule::d3d12_create_graphics_pipeline_state_hook(ID3D12Device* device, const D3D12_GRAPHICS_PIPELINE_STATE_DESC* desc, REFIID riid, void** pipeline_state) {
+ const auto self = NativePluginFramework::get_module();
+ if (desc->VS.pShaderBytecode) {
+ ShaderInfo info = self->get_shader_info((uint32_t*)desc->VS.pShaderBytecode);
+ self->m_core_create_shader(&info);
+ ShaderReplacement re = info.Replacement;
+ if (re.Source) {
+ switch (re.Type) {
+ case ShaderSourceType::HLSL:
+ compile_replacement_shader(re, "vs_5_0", &((D3D12_GRAPHICS_PIPELINE_STATE_DESC*)desc)->VS);
+ break;
+ case ShaderSourceType::BINARY:
+ ((D3D12_GRAPHICS_PIPELINE_STATE_DESC*)desc)->VS = CD3DX12_SHADER_BYTECODE(re.Source, re.Length);
+ break;
+ }
}
- else {
- self->d3d11_deinitialize_imgui();
+ }
+ if (desc->PS.pShaderBytecode) {
+ ShaderInfo info = self->get_shader_info((uint32_t*)desc->PS.pShaderBytecode);
+ self->m_core_create_shader(&info);
+ ShaderReplacement re = info.Replacement;
+ if (re.Source) {
+ switch (re.Type) {
+ case ShaderSourceType::HLSL:
+ compile_replacement_shader(re, "ps_5_0", &((D3D12_GRAPHICS_PIPELINE_STATE_DESC*)desc)->PS);
+ break;
+ case ShaderSourceType::BINARY:
+ ((D3D12_GRAPHICS_PIPELINE_STATE_DESC*)desc)->PS = CD3DX12_SHADER_BYTECODE(re.Source, re.Length);
+ break;
+ }
}
}
+ return self->m_d3d_create_graphics_pipeline_hook.call(device, desc, riid, pipeline_state);
+}
- prm->shutdown();
-
- return self->m_d3d_resize_buffers_hook.call(swap_chain, buffer_count, w, h, format, flags);
+HRESULT D3DModule::d3d12_create_compute_pipeline_state_hook(ID3D12Device* device, const D3D12_COMPUTE_PIPELINE_STATE_DESC* desc, REFIID riid, void** pipeline_state) {
+ const auto self = NativePluginFramework::get_module();
+ if (desc->CS.pShaderBytecode) {
+ ShaderInfo info = self->get_shader_info((uint32_t*)desc->CS.pShaderBytecode);
+ self->m_core_create_shader(&info);
+ ShaderReplacement re = info.Replacement;
+ if (re.Source) {
+ switch (re.Type) {
+ case ShaderSourceType::HLSL:
+ compile_replacement_shader(re, "cs_5_0", &((D3D12_COMPUTE_PIPELINE_STATE_DESC*)desc)->CS);
+ break;
+ case ShaderSourceType::BINARY:
+ ((D3D12_COMPUTE_PIPELINE_STATE_DESC*)desc)->CS = CD3DX12_SHADER_BYTECODE(re.Source, re.Length);
+ break;
+ }
+ }
+ }
+ return self->m_d3d_create_compute_pipeline_hook.call(device, desc, riid, pipeline_state);
}
HRESULT D3DModule::d3d11_present_hook(IDXGISwapChain* swap_chain, UINT sync_interval, UINT flags) {
@@ -915,27 +686,25 @@ HRESULT D3DModule::d3d11_present_hook(IDXGISwapChain* swap_chain, UINT sync_inte
const auto prm = NativePluginFramework::get_module();
const auto& config = preloader::LoaderConfig::get();
- if (self->m_is_inside_present) {
- return self->m_d3d_present_hook.call(swap_chain, sync_interval, flags);
- }
+ if (!self->m_is_inside_present) {
+ self->m_is_inside_present = true;
- self->m_is_inside_present = true;
+ if (!self->m_is_initialized) {
+ self->d3d11_initialize_imgui(swap_chain);
- if (!self->m_is_initialized) {
- self->d3d11_initialize_imgui(swap_chain);
+ if (!self->m_texture_manager) {
+ self->m_texture_manager = std::make_unique(self->m_d3d11_device, self->m_d3d11_device_context);
+ }
- if (!self->m_texture_manager) {
- self->m_texture_manager = std::make_unique(self->m_d3d11_device, self->m_d3d11_device_context);
- }
-
- if (config.get_primitive_rendering_enabled()) {
- prm->late_init(self.get(), swap_chain);
+ if (config.get_primitive_rendering_enabled()) {
+ prm->late_init(self.get(), swap_chain);
+ }
}
- }
- self->d3d11_present_hook_core(swap_chain, prm);
+ self->d3d11_present_hook_core(swap_chain, prm);
+ }
- const auto result = self->m_d3d_present_hook.call(swap_chain, sync_interval, flags);
+ HRESULT result = self->m_d3d_present_hook.call(swap_chain, sync_interval, flags);
self->m_is_inside_present = false;
return result;
@@ -956,13 +725,80 @@ void D3DModule::d3d11_present_hook_core(IDXGISwapChain* swap_chain, const std::s
ImGui_ImplDX11_RenderDrawData(draw_data);
- if (igGetIO()->ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
- {
+ if (igGetIO()->ConfigFlags & ImGuiConfigFlags_ViewportsEnable) {
igUpdatePlatformWindows();
igRenderPlatformWindowsDefault(nullptr, nullptr);
}
}
+HRESULT D3DModule::d3d11_create_vertex_shader_hook(ID3D11Device* device, const void* shader_bytecode, SIZE_T bytecode_length, ID3D11ClassLinkage* class_linkage, ID3D11VertexShader** vertex_shader) {
+ const auto self = NativePluginFramework::get_module();
+ ShaderInfo info = self->get_shader_info((uint32_t*)shader_bytecode);
+ self->m_core_create_shader(&info);
+ ShaderReplacement re = info.Replacement;
+ if (re.Source) {
+ CD3DX12_SHADER_BYTECODE sbc;
+ switch (re.Type) {
+ case ShaderSourceType::HLSL:
+ if (compile_replacement_shader(re, "vs_5_0", &sbc)) {
+ shader_bytecode = sbc.pShaderBytecode;
+ bytecode_length = sbc.BytecodeLength;
+ }
+ break;
+ case ShaderSourceType::BINARY:
+ shader_bytecode = re.Source;
+ bytecode_length = re.Length;
+ break;
+ }
+ }
+ return self->m_d3d_create_vertex_shader_hook.call(device, shader_bytecode, bytecode_length, class_linkage, vertex_shader);
+}
+
+HRESULT D3DModule::d3d11_create_pixel_shader_hook(ID3D11Device* device, const void* shader_bytecode, SIZE_T bytecode_length, ID3D11ClassLinkage* class_linkage, ID3D11PixelShader** pixel_shader) {
+ const auto self = NativePluginFramework::get_module();
+ ShaderInfo info = self->get_shader_info((uint32_t*)shader_bytecode);
+ self->m_core_create_shader(&info);
+ ShaderReplacement re = info.Replacement;
+ if (re.Source) {
+ CD3DX12_SHADER_BYTECODE sbc;
+ switch (re.Type) {
+ case ShaderSourceType::HLSL:
+ if (compile_replacement_shader(re, "ps_5_0", &sbc)) {
+ shader_bytecode = sbc.pShaderBytecode;
+ bytecode_length = sbc.BytecodeLength;
+ }
+ break;
+ case ShaderSourceType::BINARY:
+ shader_bytecode = re.Source;
+ bytecode_length = re.Length;
+ break;
+ }
+ }
+ return self->m_d3d_create_pixel_shader_hook.call(device, shader_bytecode, bytecode_length, class_linkage, pixel_shader);
+}
+
+HRESULT D3DModule::d3d11_create_compute_shader_hook(ID3D11Device* device, const void* shader_bytecode, SIZE_T bytecode_length, ID3D11ClassLinkage* class_linkage, ID3D11ComputeShader** compute_shader) {
+ const auto self = NativePluginFramework::get_module();
+ ShaderInfo info = self->get_shader_info((uint32_t*)shader_bytecode);
+ self->m_core_create_shader(&info);
+ ShaderReplacement re = info.Replacement;
+ if (re.Source) {
+ CD3DX12_SHADER_BYTECODE sbc;
+ switch (re.Type) {
+ case ShaderSourceType::HLSL:
+ if (compile_replacement_shader(re, "cs_5_0", &sbc)) {
+ shader_bytecode = sbc.pShaderBytecode;
+ bytecode_length = sbc.BytecodeLength;
+ }
+ break;
+ case ShaderSourceType::BINARY:
+ shader_bytecode = re.Source;
+ bytecode_length = re.Length;
+ break;
+ }
+ }
+ return self->m_d3d_create_compute_shader_hook.call(device, shader_bytecode, bytecode_length, class_linkage, compute_shader);
+}
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
diff --git a/mhw-cs-plugin-loader/D3DModule.h b/mhw-cs-plugin-loader/D3DModule.h
index 9a8973e..8c69812 100644
--- a/mhw-cs-plugin-loader/D3DModule.h
+++ b/mhw-cs-plugin-loader/D3DModule.h
@@ -13,6 +13,7 @@
#include
#include
+#include
class D3DModule final : public NativeModule {
template using ComPtr = Microsoft::WRL::ComPtr;
@@ -22,11 +23,9 @@ class D3DModule final : public NativeModule {
void shutdown() override;
private:
- void common_initialize();
- void initialize_for_d3d12();
- void initialize_for_d3d11();
- void initialize_for_d3d12_alt();
- void initialize_for_d3d11_alt();
+ void common_initialize(const uintptr_t render_singleton);
+ void initialize_for_d3d12(const uintptr_t renderer);
+ void initialize_for_d3d11(const uintptr_t renderer);
void d3d12_initialize_imgui(IDXGISwapChain* swap_chain);
void d3d11_initialize_imgui(IDXGISwapChain* swap_chain);
@@ -41,15 +40,17 @@ class D3DModule final : public NativeModule {
static bool is_d3d12();
- static void title_menu_ready_hook(void* gui);
-
static HRESULT d3d12_present_hook(IDXGISwapChain* swap_chain, UINT sync_interval, UINT flags);
void d3d12_present_hook_core(IDXGISwapChain* swap_chain, const std::shared_ptr& prm);
- static void d3d12_execute_command_lists_hook(ID3D12CommandQueue* command_queue, UINT num_command_lists, ID3D12CommandList* const* command_lists);
static UINT64 d3d12_signal_hook(ID3D12CommandQueue* command_queue, ID3D12Fence* fence, UINT64 value);
+ static HRESULT d3d12_create_graphics_pipeline_state_hook(ID3D12Device* device, const D3D12_GRAPHICS_PIPELINE_STATE_DESC* desc, REFIID riid, void** pipeline_state);
+ static HRESULT d3d12_create_compute_pipeline_state_hook(ID3D12Device* device, const D3D12_COMPUTE_PIPELINE_STATE_DESC* desc, REFIID riid, void** pipeline_state);
static HRESULT d3d11_present_hook(IDXGISwapChain* swap_chain, UINT sync_interval, UINT flags);
void d3d11_present_hook_core(IDXGISwapChain* swap_chain, const std::shared_ptr& prm) const;
+ static HRESULT d3d11_create_vertex_shader_hook(ID3D11Device* device, const void* shader_bytecode, SIZE_T bytecode_length, ID3D11ClassLinkage* class_linkage, ID3D11VertexShader** vertex_shader);
+ static HRESULT d3d11_create_pixel_shader_hook(ID3D11Device* device, const void* shader_bytecode, SIZE_T bytecode_length, ID3D11ClassLinkage* class_linkage, ID3D11PixelShader** pixel_shader);
+ static HRESULT d3d11_create_compute_shader_hook(ID3D11Device* device, const void* shader_bytecode, SIZE_T bytecode_length, ID3D11ClassLinkage* class_linkage, ID3D11ComputeShader** compute_shader);
static HRESULT d3d_resize_buffers_hook(IDXGISwapChain* swap_chain, UINT buffer_count, UINT w, UINT h, DXGI_FORMAT format, UINT flags);
static LRESULT my_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
@@ -69,23 +70,53 @@ class D3DModule final : public NativeModule {
ImFont* Font;
};
+ enum ShaderSourceType {
+ HLSL = 0,
+ BINARY
+ };
+
+ struct ShaderReplacement {
+ int Type;
+ unsigned char* Source;
+ int Length;
+ };
+
+ struct ShaderInfo {
+ char DxbcHash[36];
+ ShaderReplacement Replacement;
+ };
+
private:
static inline bool m_is_d3d12 = false;
bool m_is_initialized = false;
bool m_is_inside_present = false;
bool m_fonts_loaded = false;
- safetyhook::InlineHook m_title_menu_ready_hook;
+ safetyhook::MidHook m_create_renderer_hook;
safetyhook::InlineHook m_d3d_present_hook;
- safetyhook::InlineHook m_d3d_execute_command_lists_hook;
safetyhook::InlineHook m_d3d_signal_hook;
safetyhook::InlineHook m_d3d_resize_buffers_hook;
- safetyhook::MidHook m_d3d_present_hook_alt;
+ safetyhook::InlineHook m_d3d_create_graphics_pipeline_hook;
+ safetyhook::InlineHook m_d3d_create_compute_pipeline_hook;
+ safetyhook::InlineHook m_d3d_create_vertex_shader_hook;
+ safetyhook::InlineHook m_d3d_create_pixel_shader_hook;
+ safetyhook::InlineHook m_d3d_create_compute_shader_hook;
std::unique_ptr m_texture_manager;
+ static ShaderInfo get_shader_info(uint32_t* dxbc) {
+ ShaderInfo info;
+ std::string hash = std::format("{:08x}-{:08x}-{:08x}-{:08x}", dxbc[1], dxbc[2], dxbc[3], dxbc[4]);
+ std::memcpy(info.DxbcHash, hash.c_str(), 35);
+ info.DxbcHash[35] = '\0';
+ info.Replacement.Source = nullptr;
+ return info;
+ }
+
+ static bool compile_replacement_shader(ShaderReplacement& re, const char* target, D3D12_SHADER_BYTECODE* out);
+
#pragma region D3D12
ID3D12Device* m_d3d12_device = nullptr;
@@ -106,15 +137,10 @@ class D3DModule final : public NativeModule {
ID3D11Device* m_d3d11_device = nullptr;
ID3D11DeviceContext* m_d3d11_device_context = nullptr;
- IDXGISwapChain* m_d3d11_swap_chain = nullptr;
#pragma endregion
- HMODULE m_d3d12_module = nullptr;
- HMODULE m_d3d11_module = nullptr;
-
HWND m_game_window = nullptr;
- HMODULE m_game_module = nullptr;
WNDPROC m_game_window_proc = nullptr;
HWND m_temp_window = nullptr;
@@ -123,6 +149,7 @@ class D3DModule final : public NativeModule {
ImGuiContext*(*m_core_initialize_imgui)(MtSize viewport_size, MtSize window_size, bool d3d12, const char* menu_key) = nullptr;
ImDrawData*(*m_core_imgui_render)() = nullptr;
void(*m_core_render)() = nullptr;
+ void(*m_core_create_shader)(ShaderInfo* info) = nullptr;
int(*m_core_get_custom_fonts)(CustomFont** out_fonts) = nullptr;
void(*m_core_resolve_custom_fonts)() = nullptr;
void* (*m_get_singleton)(const char* name) = nullptr;
diff --git a/mhw-cs-plugin-loader/NativePluginFramework.cpp b/mhw-cs-plugin-loader/NativePluginFramework.cpp
index 066a078..908cb5d 100644
--- a/mhw-cs-plugin-loader/NativePluginFramework.cpp
+++ b/mhw-cs-plugin-loader/NativePluginFramework.cpp
@@ -64,7 +64,7 @@ const char* NativePluginFramework::get_game_revision() {
if (s_instance->m_game_revision != nullptr) {
return s_instance->m_game_revision;
}
-
+
const auto pattern = Pattern::from_string("48 83 EC 48 48 8B 05 ? ? ? ? 4C 8D 0D ? ? ? ? BA 0A 00 00 00");
const auto func = PatternScanner::find_first(pattern);
diff --git a/mhw-cs-plugin-loader/NativePluginFramework.h b/mhw-cs-plugin-loader/NativePluginFramework.h
index 4b12762..0b05dfc 100644
--- a/mhw-cs-plugin-loader/NativePluginFramework.h
+++ b/mhw-cs-plugin-loader/NativePluginFramework.h
@@ -32,7 +32,7 @@ class NativePluginFramework {
void trigger_on_pre_main();
void trigger_on_win_main();
void trigger_on_mh_main_ctor();
-
+
static void run_compatibility_checks();
static uintptr_t get_repository_address(const char* name);
static const char* get_game_revision();
diff --git a/mhw-cs-plugin-loader/PrimitiveRenderingModule.cpp b/mhw-cs-plugin-loader/PrimitiveRenderingModule.cpp
index e9e9c41..0fe26ed 100644
--- a/mhw-cs-plugin-loader/PrimitiveRenderingModule.cpp
+++ b/mhw-cs-plugin-loader/PrimitiveRenderingModule.cpp
@@ -105,8 +105,8 @@ void PrimitiveRenderingModule::render_primitives_for_d3d11(ID3D11DeviceContext*
m_capsules = std::span(capsules, m_capsule_count);
m_lines = std::span(lines, m_line_count);
- //if (m_spheres.empty() &&
- // m_cubes.empty() &&
+ //if (m_spheres.empty() &&
+ // m_cubes.empty() &&
// m_capsules.empty() &&
// m_lines.empty()) {
// return;
@@ -292,15 +292,15 @@ void PrimitiveRenderingModule::render_primitives_for_d3d11(ID3D11DeviceContext*
-XMVectorGetY(v), -XMVectorGetX(v), 0, 0,
0, 0, 0, 0 };
const XMMATRIX vx2 = XMMatrixMultiply(vx, vx);
-
+
rotation = XMMatrixAdd(XMMatrixAdd(XMMatrixIdentity(), vx), vx2 * (1.0f / (1.0f + c)));
}
// Scale
const XMMATRIX scale_hemisphere = XMMatrixScaling(capsule.capsule.r, capsule.capsule.r, capsule.capsule.r);
const XMMATRIX scale_cylinder = XMMatrixScaling(
- capsule.capsule.r,
- XMVectorGetX(XMVector3Length(p1 - p0)) * 0.5f,
+ capsule.capsule.r,
+ XMVectorGetX(XMVector3Length(p1 - p0)) * 0.5f,
capsule.capsule.r
);
@@ -388,7 +388,7 @@ void PrimitiveRenderingModule::render_primitives_for_d3d11(ID3D11DeviceContext*
const auto params = (LineParams*)msr.pData;
params->Thickness = m_line_thickness;
context->Unmap(m_d3d11_line_params_buffer.Get(), 0);
-
+
const std::array constant_buffers = {
m_d3d11_viewproj_buffer.Get(),
m_d3d11_line_params_buffer.Get()
@@ -451,7 +451,7 @@ void PrimitiveRenderingModule::render_primitives_for_d3d12(IDXGISwapChain3* swap
m_capsules = std::span(capsules, m_capsule_count);
m_lines = std::span(lines, m_line_count);
- //if (m_spheres.empty() &&
+ //if (m_spheres.empty() &&
// m_cubes.empty() &&
// m_capsules.empty() &&
// m_lines.empty()) {
@@ -465,7 +465,7 @@ void PrimitiveRenderingModule::render_primitives_for_d3d12(IDXGISwapChain3* swap
}
// Set up common pipeline state
-
+
const FrameContext& frame_context = m_d3d12_frame_contexts[swap_chain->GetCurrentBackBufferIndex()];
HandleResult(m_d3d12_command_allocator->Reset());
@@ -487,9 +487,9 @@ void PrimitiveRenderingModule::render_primitives_for_d3d12(IDXGISwapChain3* swap
m_d3d12_command_list->RSSetViewports(1, &m_d3d12_viewport);
m_d3d12_command_list->RSSetScissorRects(1, &m_d3d12_scissor_rect);
m_d3d12_command_list->OMSetRenderTargets(
- 1,
- &frame_context.RenderTargetDescriptor,
- false,
+ 1,
+ &frame_context.RenderTargetDescriptor,
+ false,
&m_d3d12_depth_stencil_view
);
@@ -524,8 +524,8 @@ void PrimitiveRenderingModule::render_primitives_for_d3d12(IDXGISwapChain3* swap
// Spheres ------------------------------
if (m_sphere_count != 0) {
// Build Instance Data
- const D3D12_RANGE range{
- 0,
+ const D3D12_RANGE range{
+ 0,
sizeof(Instance) * std::min((u32)m_sphere_count, MAX_INSTANCES)
};
Instance* data = nullptr;
@@ -823,7 +823,7 @@ void PrimitiveRenderingModule::late_init_d3d11(D3DModule* d3dmodule) {
HandleResult(d3dmodule->m_d3d11_device->CreateBuffer(&bd, nullptr, m_d3d11_transform_buffer.GetAddressOf()));
HandleResult(d3dmodule->m_d3d11_device->CreateBuffer(&bd, nullptr, m_d3d11_htop_transform_buffer.GetAddressOf()));
HandleResult(d3dmodule->m_d3d11_device->CreateBuffer(&bd, nullptr, m_d3d11_hbottom_transform_buffer.GetAddressOf()));
-
+
// Create Line Vertex Buffer
bd.ByteWidth = sizeof LineVertex * MAX_LINES * 2;
bd.Usage = D3D11_USAGE_DYNAMIC;
@@ -1047,15 +1047,9 @@ void PrimitiveRenderingModule::late_init_d3d12(D3DModule* d3dmodule, IDXGISwapCh
ComPtr signature_blob;
ComPtr error_blob;
-
- const auto serialize_root_signature = (decltype(D3D12SerializeRootSignature)*)GetProcAddress(
- d3dmodule->m_d3d12_module, "D3D12SerializeRootSignature"
- );
- if (!serialize_root_signature) {
- dlog::error("Failed to get D3D12SerializeRootSignature");
- }
- HandleResult(serialize_root_signature(
+ // d3d12.lib linked in D3DModule.cpp
+ HandleResult(D3D12SerializeRootSignature(
&root_signature_desc,
D3D_ROOT_SIGNATURE_VERSION_1,
signature_blob.GetAddressOf(),
@@ -1089,7 +1083,7 @@ void PrimitiveRenderingModule::late_init_d3d12(D3DModule* d3dmodule, IDXGISwapCh
signature_blob.Reset();
error_blob.Reset();
- HandleResult(serialize_root_signature(
+ HandleResult(D3D12SerializeRootSignature(
&root_signature_desc,
D3D_ROOT_SIGNATURE_VERSION_1,
signature_blob.GetAddressOf(),
@@ -1163,7 +1157,7 @@ void PrimitiveRenderingModule::late_init_d3d12(D3DModule* d3dmodule, IDXGISwapCh
depth_stencil_desc.StencilEnable = false;
// Blend State
-
+
D3D12_BLEND_DESC blend_desc{};
blend_desc.IndependentBlendEnable = false;
blend_desc.RenderTarget[0].BlendEnable = true;
@@ -1174,7 +1168,7 @@ void PrimitiveRenderingModule::late_init_d3d12(D3DModule* d3dmodule, IDXGISwapCh
blend_desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;
blend_desc.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
-
+
// Pipeline State
const auto sc3 = (IDXGISwapChain3*)swap_chain;
DXGI_SWAP_CHAIN_DESC swap_chain_desc{};
@@ -1380,7 +1374,7 @@ void PrimitiveRenderingModule::late_init_d3d12(D3DModule* d3dmodule, IDXGISwapCh
depth_clear_value.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depth_clear_value.DepthStencil.Depth = 1.0f;
depth_clear_value.DepthStencil.Stencil = 0;
-
+
const auto default_heap_properties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
HandleResult(d3dmodule->m_d3d12_device->CreateCommittedResource(
&default_heap_properties,