From 3a844cc3ca6edb74a0aeb2d3fe3f032a2c5f0a7e Mon Sep 17 00:00:00 2001 From: Robert Krawczyk Date: Sat, 13 Mar 2021 03:51:58 +0100 Subject: [PATCH] Changes: Fixed DXVK window starting in background and required clicking to activate Added experimental (disabled by default) DiscardUIVertexBuffer option Improved D3D9 reference counting Two step initialization, check is correct window was created, then initialize 2s after IDirect3D9::CreateDevice call Other: Fix some include hell Settings.h now include all comments so it will autogenerated ini file Deleted IDirect3DVertexBuffer9.cpp/h --- Common/Logger.h | 9 ++- d3d9ex/AutoFix.cpp | 90 +++++++++++++++--------- d3d9ex/Context.cpp | 67 ++++++++++++------ d3d9ex/Context.h | 33 ++++----- d3d9ex/IDirect3D9.cpp | 20 ++---- d3d9ex/IDirect3D9.h | 50 +++++++++++--- d3d9ex/IDirect3DDevice9.cpp | 17 +---- d3d9ex/IDirect3DDevice9.h | 57 ++++++++++++---- d3d9ex/IDirect3DVertexBuffer9.cpp | 104 ---------------------------- d3d9ex/IDirect3DVertexBuffer9.h | 42 ------------ d3d9ex/Settings.h | 109 +++++++++++++++++++++++------- d3d9ex/VertexFix.cpp | 32 +++++++++ d3d9ex/Wrapper.h | 8 +-- d3d9ex/d3d9ex.vcxproj | 13 ++-- d3d9ex/d3d9ex.vcxproj.filters | 11 ++- d3d9ex/stdafx.h | 7 +- 16 files changed, 348 insertions(+), 321 deletions(-) delete mode 100644 d3d9ex/IDirect3DVertexBuffer9.cpp delete mode 100644 d3d9ex/IDirect3DVertexBuffer9.h create mode 100644 d3d9ex/VertexFix.cpp diff --git a/Common/Logger.h b/Common/Logger.h index 71ce53e..4e10f5b 100644 --- a/Common/Logger.h +++ b/Common/Logger.h @@ -5,10 +5,13 @@ #include #include +#include #include "StringUtil.h" #include "WinUtil.h" +#define LOGGER_DISABLE_MUTEX + #ifndef LOGGER_DISABLE class Logger { @@ -27,7 +30,9 @@ public: CloseHandle(m_file); } +#ifndef LOGGER_DISABLE_MUTEX std::mutex& writeMutex() const { return m_writeMutex; } +#endif static Logger& Logger::Get() { @@ -38,7 +43,7 @@ public: bool File(const std::string& filename) { std::string logpath = FullPathFromPath(filename); - m_file = CreateFileA(logpath.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + m_file = CreateFileA(logpath.c_str(), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL); OutputDebugStringA(logpath.c_str()); if (m_file != INVALID_HANDLE_VALUE) @@ -127,7 +132,9 @@ inline void LogConsole(const char* title = nullptr) inline void PrintLog(const char* format, ...) { +#ifndef LOGGER_DISABLE_MUTEX const std::lock_guard lock(Logger::Get().writeMutex()); +#endif va_list args; va_start(args, format); Logger::Get().Print(format, args); diff --git a/d3d9ex/AutoFix.cpp b/d3d9ex/AutoFix.cpp index 172c18a..60c0f59 100644 --- a/d3d9ex/AutoFix.cpp +++ b/d3d9ex/AutoFix.cpp @@ -1,7 +1,10 @@ #include "stdafx.h" +#include "Logger.h" +#include "MemPatch.h" + #include "Context.h" -#include "IDirect3DVertexBuffer9.h" +//#include "IDirect3DVertexBuffer9.h" void MainContext::EnableAutoFix() { @@ -24,11 +27,17 @@ void MainContext::EnableAutoFix() } } -const std::map MainContext::behaviorflags_fixes = +const std::map MainContext::behaviorflags_add = { }; +const std::map MainContext::behaviorflags_sub = +{ + //{ AutoFixes::FINAL_FANTASY_XIII, D3DCREATE_PUREDEVICE }, + //{ AutoFixes::FINAL_FANTASY_XIII2, D3DCREATE_PUREDEVICE } +}; + void MainContext::FixBehaviorFlagConflict(const DWORD flags_in, DWORD* flags_out) { if (flags_in & D3DCREATE_SOFTWARE_VERTEXPROCESSING) @@ -48,24 +57,26 @@ void MainContext::FixBehaviorFlagConflict(const DWORD flags_in, DWORD* flags_out } } -bool MainContext::ApplyBehaviorFlagsFix(DWORD* flags) +void MainContext::ApplyBehaviorFlagsFix(DWORD* flags) { - if (autofix == AutoFixes::NONE) return false; + if (autofix == AutoFixes::NONE) return; - auto&& fix = behaviorflags_fixes.find(autofix); - if (fix != behaviorflags_fixes.end()) + auto&& add = behaviorflags_add.find(autofix); + if (add != behaviorflags_add.end()) + FixBehaviorFlagConflict(add->second, flags); + + auto&& sub = behaviorflags_sub.find(autofix); + if (sub != behaviorflags_sub.end()) { - FixBehaviorFlagConflict(fix->second, flags); - return true; + *flags = *flags & ~sub->second; + FixBehaviorFlagConflict(sub->second, flags); } - - return false; } HRESULT MainContext::SetScissorRect(IDirect3DDevice9* pIDirect3DDevice9, CONST RECT* rect) { if (rect) - { + { RECT* r = const_cast(rect); r->left = (LONG)(r->left * scissor_scaling_factor_w); r->top = (LONG)(r->top * scissor_scaling_factor_h); @@ -78,6 +89,10 @@ HRESULT MainContext::SetScissorRect(IDirect3DDevice9* pIDirect3DDevice9, CONST R HRESULT MainContext::SetViewport(IDirect3DDevice9* pIDirect3DDevice9, CONST D3DVIEWPORT9* pViewport) { + // DXVK fixes this better + if(IsDXVK()) + return pIDirect3DDevice9->SetViewport(pViewport); + if (pViewport) { D3DVIEWPORT9* vp = const_cast(pViewport); @@ -88,43 +103,52 @@ HRESULT MainContext::SetViewport(IDirect3DDevice9* pIDirect3DDevice9, CONST D3DV vp->Height--; vp->Y++; + return pIDirect3DDevice9->SetViewport(vp); } - return pIDirect3DDevice9->SetViewport(vp); } return pIDirect3DDevice9->SetViewport(pViewport); } +// hate this workaround but we cant directly mix d3d9 include with and without defined CINTERFACE +namespace cinterface { + void VertexBufferFix(IDirect3DVertexBuffer9* pVertexBuffer); +} + HRESULT MainContext::CreateVertexBuffer(IDirect3DDevice9* pIDirect3DDevice9, UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle) { - switch (autofix) + if (autofix == AutoFixes::FINAL_FANTASY_XIII || + autofix == AutoFixes::FINAL_FANTASY_XIII2) { - case AutoFixes::FINAL_FANTASY_XIII: - case AutoFixes::FINAL_FANTASY_XIII2: // Both games lock a vertex buffer 358400 before drawing any 2D element on screen (sometimes multiple times per frame) if (Length == 358400 && Pool == D3DPOOL_MANAGED) { Usage = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY; Pool = D3DPOOL_SYSTEMMEM; + HRESULT hr = pIDirect3DDevice9->CreateVertexBuffer(Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle); + + if (config.GetFFXIIIDiscardUIVertexBuffer() && ppVertexBuffer && *ppVertexBuffer) + { + //Pool = D3DPOOL_DEFAULT; + cinterface::VertexBufferFix(*ppVertexBuffer); + } + return hr; } - - // Crashing on Lock/Unlock, why??? - // //IDirect3DVertexBuffer9* buffer = nullptr; - // //HRESULT hr = pIDirect3DDevice9->CreateVertexBuffer(Length, Usage, FVF, Pool, &buffer, NULL); - // //if (FAILED(hr)) - // //{ - // // return pIDirect3DDevice9->CreateVertexBuffer(Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle); - // //} - - // //if(ppVertexBuffer) *ppVertexBuffer = new hkIDirect3DVertexBuffer9(pIDirect3DDevice9, buffer); - // //return hr; - break; } return pIDirect3DDevice9->CreateVertexBuffer(Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle); } - -void MainContext::OneTimeFix(std::unique_ptr& className) +bool MainContext::OneTimeFixInit(std::unique_ptr& className) { if (wcscmp(className.get(), L"SQEX.CDev.Engine.Framework.MainWindow") == 0) { + otf_init = true; + } + return otf_init; +} + +void MainContext::OneTimeFix() +{ + if (otf_init) + { + otf_init = false; std::thread fix(&context.Fix_Thread); fix.detach(); } @@ -132,7 +156,11 @@ void MainContext::OneTimeFix(std::unique_ptr& className) void MainContext::Fix_Thread() { + auto start = std::chrono::high_resolution_clock::now(); std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration elapsed = end - start; + PrintLog("Waited %f ms", elapsed.count()); std::lock_guard lock(context.fix_mutex); if (context.autofix == AutoFixes::FINAL_FANTASY_XIII) { @@ -414,7 +442,3 @@ void MainContext::FF13_2_CreateSetFrameRateCodeBlock() void MainContext::PrintVersionInfo() { PrintLog("FF13Fix 1.5.2 https://github.com/rebtd7/FF13Fix"); } - -bool MainContext::AreAlmostTheSame(float a, float b) { - return fabs(a - b) < 0.01f; -} diff --git a/d3d9ex/Context.cpp b/d3d9ex/Context.cpp index a1ab8c6..f4f0974 100644 --- a/d3d9ex/Context.cpp +++ b/d3d9ex/Context.cpp @@ -1,11 +1,17 @@ #include "stdafx.h" -#include -#include "Wrapper.h" - -#include "Context.h" -#include "IDirect3D9.h" #include +#include + + +#include "Logger.h" + +#include "MinHook.h" +#include "SimpleIni.h" + +#include "IDirect3D9.h" +#include "Context.h" +#include "Wrapper.h" MainContext context; @@ -22,8 +28,8 @@ Config::Config() // save file and reload ini.Reset(); -#define SETTING(_type, _func, _var, _section, _defaultval) \ - ini.Set##_func(L#_section, L#_var, _defaultval) +#define SETTING(_type, _func, _var, _section, _defaultval, _comment) \ + ini.Set##_func(L#_section, L#_var, _defaultval, _comment) #include "Settings.h" #undef SETTING @@ -33,13 +39,13 @@ Config::Config() ini.LoadFile(inifile.c_str()); } -#define SETTING(_type, _func, _var, _section, _defaultval) \ +#define SETTING(_type, _func, _var, _section, _defaultval, _comment) \ _var = ini.Get##_func(L#_section, L#_var) #include "Settings.h" #undef SETTING } -MainContext::MainContext() : oldWndProc(nullptr) +MainContext::MainContext() { LogFile("FF13Fix.log"); context.PrintVersionInfo(); @@ -124,7 +130,7 @@ bool MainContext::ApplyPresentationParameters(D3DPRESENT_PARAMETERS* pPresentati if (pPresentationParameters) { // -1 = Auto, enabled when no DXVK is used - if (config.GetOptionsTripleBuffering() == 1 || (config.GetOptionsTripleBuffering() == -1 && !D3D9DLL::Get().IsDXVK())) + if (config.GetOptionsTripleBuffering() == 1 || (config.GetOptionsTripleBuffering() == -1 && !IsDXVK())) { pPresentationParameters->BackBufferCount = 3; PrintLog("BackBufferCount: BackBufferCount set to %u", pPresentationParameters->BackBufferCount); @@ -194,18 +200,28 @@ bool MainContext::CheckWindow(HWND hWnd) PrintLog("HWND 0x%p: ClassName \"%ls\", WindowName: \"%ls\"", hWnd, className.get(), windowName.get()); - OneTimeFix(className); - - bool class_found = config.GetBorderlessWindowClass().compare(className.get()) == 0; - bool window_found = config.GetBorderlessWindowName().compare(windowName.get()) == 0; + bool class_found = config.GetWindowWindowClass().compare(className.get()) == 0; + bool window_found = config.GetWindowWindowName().compare(windowName.get()) == 0; bool force = config.GetBorderlessAllWindows(); + bool ff13fix = OneTimeFixInit(className); - return class_found || window_found || force; + return class_found || window_found || force || ff13fix; } -void MainContext::ApplyWndProc(HWND hWnd) +void MainContext::ApplyWindow(HWND hWnd) { - if (config.GetOptionsAlwaysActive() || config.GetOptionsHideCursor()) + HWND insertAfter = HWND_TOP; + if (config.GetWindowTopMost() && !context.IsDXVK()) + insertAfter = HWND_TOPMOST; + + SetWindowPos(hWnd, insertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); + SetFocus(hWnd); + + // fixes DXVK window in background, no need to click anymore + if (context.IsDXVK()) + SetForegroundWindow(hWnd); + + if (config.GetOptionsAlwaysActive() || config.GetOptionsHideCursor() || IsDXVK()) { context.oldWndProc = (WNDPROC)context.TrueSetWindowLongA(hWnd, GWLP_WNDPROC, (LONG_PTR)context.WindowProc); } @@ -227,7 +243,12 @@ void MainContext::ApplyBorderless(HWND hWnd) int cx = GetSystemMetrics(SM_CXSCREEN); int cy = GetSystemMetrics(SM_CYSCREEN); - SetWindowPos(hWnd, HWND_TOP, 0, 0, cx, cy, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); + HWND insertAfter = HWND_TOP; + + if (config.GetWindowTopMost()) + insertAfter = HWND_TOPMOST; + + SetWindowPos(hWnd, insertAfter, 0, 0, cx, cy, SWP_SHOWWINDOW | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); SetFocus(hWnd); PrintLog("HWND 0x%p: Borderless dwStyle: %lX->%lX", hWnd, dwStyle, new_dwStyle); @@ -252,7 +273,7 @@ LRESULT CALLBACK MainContext::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP if (context.config.GetOptionsAlwaysActive()) return TRUE; - if (!context.config.GetOptionsForceHideCursor()) + if (!context.config.GetOptionsForceHideCursor() || context.IsDXVK()) while (::ShowCursor(TRUE) < 0); break; } @@ -263,7 +284,7 @@ LRESULT CALLBACK MainContext::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP } - if (context.config.GetOptionsForceHideCursor()) + if (context.config.GetOptionsForceHideCursor() || context.IsDXVK()) while (::ShowCursor(FALSE) >= 0); return CallWindowProc(context.oldWndProc, hWnd, uMsg, wParam, lParam); @@ -320,7 +341,7 @@ HWND WINAPI MainContext::HookCreateWindowExA(DWORD dwExStyle, LPCSTR lpClassName if (context.CheckWindow(hWnd)) { - context.ApplyWndProc(hWnd); + context.ApplyWindow(hWnd); context.ApplyBorderless(hWnd); } @@ -338,9 +359,11 @@ HWND WINAPI MainContext::HookCreateWindowExW(DWORD dwExStyle, LPCWSTR lpClassNam if (context.CheckWindow(hWnd)) { - context.ApplyWndProc(hWnd); + context.ApplyWindow(hWnd); context.ApplyBorderless(hWnd); } return hWnd; } + +bool MainContext::IsDXVK() { return D3D9DLL::Get().IsDXVK(); } \ No newline at end of file diff --git a/d3d9ex/Context.h b/d3d9ex/Context.h index 60a88ee..ffe67d6 100644 --- a/d3d9ex/Context.h +++ b/d3d9ex/Context.h @@ -1,16 +1,13 @@ #pragma once -#include -#include "d3d9.h" -#include -#include "SimpleIni.h" -#include "XInputManager.h" -#include "MemPatch.h" +#include +#include -struct hkIDirect3D9; +#include "Types.h" +#include "XInputManager.h" static const char* inifilename = "FF13Fix.ini"; -#define CONFIG_VERSION 5 +#define CONFIG_VERSION 6 class Config { @@ -20,7 +17,7 @@ public: Config(); -#define SETTING(_type, _func, _var, _section, _defaultval) \ +#define SETTING(_type, _func, _var, _section, _defaultval, _comment) \ private: _type _var; \ public: const _type& Get##_section##_var() const { return _var; }; #include "Settings.h" @@ -46,10 +43,10 @@ class MainContext public: MainContext(); - ~MainContext(); + virtual ~MainContext(); bool ApplyPresentationParameters(D3DPRESENT_PARAMETERS* pPresentationParameters); - bool ApplyBehaviorFlagsFix(DWORD* flags); + void ApplyBehaviorFlagsFix(DWORD* flags); HRESULT SetScissorRect(IDirect3DDevice9* pIDirect3DDevice9, CONST RECT* rect); HRESULT CreateVertexBuffer(IDirect3DDevice9* pIDirect3DDevice9, UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle); HRESULT SetViewport(IDirect3DDevice9* pIDirect3DDevice9, CONST D3DVIEWPORT9* pViewport); @@ -57,10 +54,12 @@ public: bool CheckWindow(HWND hWnd); - void ApplyWndProc(HWND hWnd); + void ApplyWindow(HWND hWnd); void ApplyBorderless(HWND hWnd); Config config; + void OneTimeFix(); + bool IsDXVK(); private: enum class AutoFixes : u32 @@ -118,12 +117,12 @@ private: XInputManager* xinputManager; void FixBehaviorFlagConflict(const DWORD flags_in, DWORD* flags_out); - static const std::map behaviorflags_fixes; + static const std::map behaviorflags_add; + static const std::map behaviorflags_sub; static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - WNDPROC oldWndProc; + WNDPROC oldWndProc = nullptr; - bool AreAlmostTheSame(float a, float b); void PrintVersionInfo(); void FF13_InitializeGameAddresses(); @@ -141,7 +140,9 @@ private: void FF13_2_OneTimeFixes(); void FF13_2_EnableControllerVibration(); - void OneTimeFix(std::unique_ptr& className); + bool OneTimeFixInit(std::unique_ptr& className); + std::atomic_bool otf_init = false; + static void Fix_Thread(); }; diff --git a/d3d9ex/IDirect3D9.cpp b/d3d9ex/IDirect3D9.cpp index 04a7f49..2188af5 100644 --- a/d3d9ex/IDirect3D9.cpp +++ b/d3d9ex/IDirect3D9.cpp @@ -2,6 +2,8 @@ // generated using wrapper_gen.rb #include "stdafx.h" + +#include "Logger.h" #include "Context.h" #include "IDirect3D9.h" @@ -17,7 +19,6 @@ HRESULT APIENTRY hkIDirect3D9::QueryInterface(REFIID riid, void** ppvObj) { riid == __uuidof(IDirect3D9)) { *ppvObj = static_cast(this); - AddRef(); return S_OK; } @@ -25,21 +26,6 @@ HRESULT APIENTRY hkIDirect3D9::QueryInterface(REFIID riid, void** ppvObj) { return E_NOINTERFACE; } -ULONG APIENTRY hkIDirect3D9::AddRef() { - PrintLog(__FUNCTION__); - return _InterlockedIncrement(&m_refCount); -} - -ULONG APIENTRY hkIDirect3D9::Release() { - PrintLog(__FUNCTION__); - const LONG ref = _InterlockedDecrement(&m_refCount); - if (ref == 0) - { - delete this; - } - return ref; -} - HRESULT APIENTRY hkIDirect3D9::RegisterSoftwareDevice(void* pInitializeFunction) { IDirect3D9_PrintLog(__FUNCTION__); return m_pWrapped->RegisterSoftwareDevice(pInitializeFunction); @@ -151,6 +137,8 @@ HRESULT APIENTRY hkIDirect3D9::CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, return hr; } + context.OneTimeFix(); + *ppReturnedDeviceInterface = new hkIDirect3DDevice9(device); return hr; } diff --git a/d3d9ex/IDirect3D9.h b/d3d9ex/IDirect3D9.h index 66c9f60..4bb91c8 100644 --- a/d3d9ex/IDirect3D9.h +++ b/d3d9ex/IDirect3D9.h @@ -1,15 +1,33 @@ // wrapper for IDirect3D9 in d3d9.h // generated using wrapper_gen.rb -#include "d3d9.h" +#include + #include "IDirect3DDevice9.h" interface hkIDirect3D9 final : public IDirect3D9 { public: // original interface STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj); - STDMETHOD_(ULONG, AddRef)(); - STDMETHOD_(ULONG, Release)(); + ULONG STDMETHODCALLTYPE AddRef() { + uint32_t refCount = m_refCount++; + if (!refCount) + AddRefPrivate(); + return refCount + 1; + } + + ULONG STDMETHODCALLTYPE Release() { + ULONG refCount = this->m_refCount; + if (refCount != 0ul) { + this->m_refCount--; + refCount--; + + if (refCount == 0ul) + this->ReleasePrivate(); + } + + return refCount; + } STDMETHOD(RegisterSoftwareDevice)(void* pInitializeFunction); STDMETHOD_(UINT, GetAdapterCount)(); STDMETHOD(GetAdapterIdentifier)(UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier); @@ -25,20 +43,32 @@ public: STDMETHOD_(HMONITOR, GetAdapterMonitor)(UINT Adapter); STDMETHOD(CreateDevice)(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface); -public: - hkIDirect3D9(IDirect3D9 *pIDirect3D9) + + hkIDirect3D9(IDirect3D9* pIDirect3D9) : m_pWrapped(pIDirect3D9) { + m_pWrapped->AddRef(); } + virtual ~hkIDirect3D9(){while (m_pWrapped->Release());} + + private: - ~hkIDirect3D9() - { - m_pWrapped->Release(); + IDirect3D9* m_pWrapped; + std::atomic m_refCount = { 0ul }; + std::atomic m_refPrivate = { 1ul }; + + void AddRefPrivate() { + ++m_refPrivate; } - LONG m_refCount = 1; - IDirect3D9 *m_pWrapped; + void ReleasePrivate() { + uint32_t refPrivate = --m_refPrivate; + if (!refPrivate) { + m_refPrivate += 0x80000000; + delete this; + } + } }; diff --git a/d3d9ex/IDirect3DDevice9.cpp b/d3d9ex/IDirect3DDevice9.cpp index b863809..5d4bae7 100644 --- a/d3d9ex/IDirect3DDevice9.cpp +++ b/d3d9ex/IDirect3DDevice9.cpp @@ -3,6 +3,8 @@ #pragma once #include "stdafx.h" + +#include "Logger.h" #include "Context.h" #include "IDirect3DDevice9.h" @@ -19,7 +21,6 @@ HRESULT APIENTRY hkIDirect3DDevice9::QueryInterface(REFIID riid, void** ppvObj) riid == __uuidof(IDirect3DDevice9)) { *ppvObj = static_cast(this); - AddRef(); return S_OK; } @@ -27,20 +28,6 @@ HRESULT APIENTRY hkIDirect3DDevice9::QueryInterface(REFIID riid, void** ppvObj) return E_NOINTERFACE; } -ULONG APIENTRY hkIDirect3DDevice9::AddRef() { - IDirect3DDevice9_PrintLog(__FUNCTION__); - return _InterlockedIncrement(&m_refCount); -} - -ULONG APIENTRY hkIDirect3DDevice9::Release() { - const LONG ref = _InterlockedDecrement(&m_refCount); - if (ref == 0) - { - delete this; - } - return ref; -} - HRESULT APIENTRY hkIDirect3DDevice9::TestCooperativeLevel() { IDirect3DDevice9_PrintLog(__FUNCTION__); return m_pWrapped->TestCooperativeLevel(); diff --git a/d3d9ex/IDirect3DDevice9.h b/d3d9ex/IDirect3DDevice9.h index 86cc02a..d034a58 100644 --- a/d3d9ex/IDirect3DDevice9.h +++ b/d3d9ex/IDirect3DDevice9.h @@ -2,21 +2,38 @@ // generated using wrapper_gen.rb #pragma once -#include "d3d9.h" +#include interface hkIDirect3DDevice9 final : public IDirect3DDevice9 { public: // original interface STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj); - STDMETHOD_(ULONG, AddRef)(); - STDMETHOD_(ULONG, Release)(); + ULONG STDMETHODCALLTYPE AddRef() { + uint32_t refCount = m_refCount++; + if (!refCount) + AddRefPrivate(); + return refCount + 1; + } + + ULONG STDMETHODCALLTYPE Release() { + ULONG refCount = this->m_refCount; + if (refCount != 0ul) { + this->m_refCount--; + refCount--; + + if (refCount == 0ul) + this->ReleasePrivate(); + } + + return refCount; + } STDMETHOD(TestCooperativeLevel)(); STDMETHOD_(UINT, GetAvailableTextureMem)(); STDMETHOD(EvictManagedResources)(); STDMETHOD(GetDirect3D)(IDirect3D9** ppD3D9); STDMETHOD(GetDeviceCaps)(D3DCAPS9* pCaps); STDMETHOD(GetDisplayMode)(UINT iSwapChain, D3DDISPLAYMODE* pMode); - STDMETHOD(GetCreationParameters)(D3DDEVICE_CREATION_PARAMETERS *pParameters); + STDMETHOD(GetCreationParameters)(D3DDEVICE_CREATION_PARAMETERS* pParameters); STDMETHOD(SetCursorProperties)(UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap); STDMETHOD_(void, SetCursorPosition)(int X, int Y, DWORD Flags); STDMETHOD_(BOOL, ShowCursor)(BOOL bShow); @@ -81,7 +98,7 @@ public: STDMETHOD(SetPaletteEntries)(UINT PaletteNumber, CONST PALETTEENTRY* pEntries); STDMETHOD(GetPaletteEntries)(UINT PaletteNumber, PALETTEENTRY* pEntries); STDMETHOD(SetCurrentTexturePalette)(UINT PaletteNumber); - STDMETHOD(GetCurrentTexturePalette)(UINT *PaletteNumber); + STDMETHOD(GetCurrentTexturePalette)(UINT* PaletteNumber); STDMETHOD(SetScissorRect)(CONST RECT* pRect); STDMETHOD(GetScissorRect)(RECT* pRect); STDMETHOD(SetSoftwareVertexProcessing)(BOOL bSoftware); @@ -127,19 +144,29 @@ public: STDMETHOD(DeletePatch)(UINT Handle); STDMETHOD(CreateQuery)(D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery); - public: - hkIDirect3DDevice9(IDirect3DDevice9 *pIDirect3DDevice9) - : m_pWrapped(pIDirect3DDevice9) - { - } - -private: - ~hkIDirect3DDevice9() + hkIDirect3DDevice9(IDirect3DDevice9* pIDirect3DDevice9) + : m_pWrapped(pIDirect3DDevice9) { - m_pWrapped->Release(); + m_pWrapped->AddRef(); } - LONG m_refCount = 1; + virtual ~hkIDirect3DDevice9() { while (m_pWrapped->Release()); } + +private: IDirect3DDevice9* m_pWrapped; + std::atomic m_refCount = { 0ul }; + std::atomic m_refPrivate = { 1ul }; + + void AddRefPrivate() { + ++m_refPrivate; + } + + void ReleasePrivate() { + uint32_t refPrivate = --m_refPrivate; + if (!refPrivate) { + m_refPrivate += 0x80000000; + delete this; + } + } }; diff --git a/d3d9ex/IDirect3DVertexBuffer9.cpp b/d3d9ex/IDirect3DVertexBuffer9.cpp deleted file mode 100644 index 61f15fe..0000000 --- a/d3d9ex/IDirect3DVertexBuffer9.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// wrapper for IDirect3DVertexBuffer9 in d3d9.h -// generated using wrapper_gen.rb - -#include "stdafx.h" -#include "Context.h" - -#include "IDirect3D9.h" -#include "IDirect3DDevice9.h" -#include "IDirect3DVertexBuffer9.h" - -#define IDirect3DVertexBuffer9_PrintLog(format, ...) PrintLog(format, __VA_ARGS__); - -HRESULT APIENTRY hkIDirect3DVertexBuffer9::QueryInterface(REFIID riid, void** ppvObj) { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__); - if (ppvObj == nullptr) return E_POINTER; - - if (riid == __uuidof(IUnknown) || - riid == __uuidof(IDirect3DResource9) || - riid == __uuidof(IDirect3DVertexBuffer9)) - { - *ppvObj = static_cast(this); - AddRef(); - return S_OK; - } - - *ppvObj = nullptr; - return E_NOINTERFACE; -} - -ULONG APIENTRY hkIDirect3DVertexBuffer9::AddRef() { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__); - return _InterlockedIncrement(&m_refCount); -} - -ULONG APIENTRY hkIDirect3DVertexBuffer9::Release() { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__); - const LONG ref = _InterlockedDecrement(&m_refCount); - if (ref == 0) - { - delete this; - } - return ref; -} - -HRESULT APIENTRY hkIDirect3DVertexBuffer9::GetDevice(IDirect3DDevice9** ppDevice) { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__); - - if (ppDevice == nullptr) - return D3DERR_INVALIDCALL; - - m_pIDirect3DDevice9->AddRef(); - *ppDevice = m_pIDirect3DDevice9; - return D3D_OK; -} - -HRESULT APIENTRY hkIDirect3DVertexBuffer9::SetPrivateData(REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__ " %s", GUIDtoStringA(refguid)); - return m_pWrapped->SetPrivateData(refguid, pData, SizeOfData, Flags); -} - -HRESULT APIENTRY hkIDirect3DVertexBuffer9::GetPrivateData(REFGUID refguid, void* pData, DWORD* pSizeOfData) { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__ " %s", GUIDtoStringA(refguid)); - return m_pWrapped->GetPrivateData(refguid, pData, pSizeOfData); -} - -HRESULT APIENTRY hkIDirect3DVertexBuffer9::FreePrivateData(REFGUID refguid) { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__); - return m_pWrapped->FreePrivateData(refguid); -} - -DWORD APIENTRY hkIDirect3DVertexBuffer9::SetPriority(DWORD PriorityNew) { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__); - return m_pWrapped->SetPriority(PriorityNew); -} - -DWORD APIENTRY hkIDirect3DVertexBuffer9::GetPriority() { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__); - return m_pWrapped->GetPriority(); -} - -void APIENTRY hkIDirect3DVertexBuffer9::PreLoad() { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__); - return m_pWrapped->PreLoad(); -} - -D3DRESOURCETYPE APIENTRY hkIDirect3DVertexBuffer9::GetType() { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__); - return m_pWrapped->GetType(); -} - -HRESULT APIENTRY hkIDirect3DVertexBuffer9::Lock(UINT OffsetToLock, UINT SizeToLock, void** ppbData, DWORD Flags) { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__); - return m_pWrapped->Lock(OffsetToLock, SizeToLock, ppbData, Flags); -} - -HRESULT APIENTRY hkIDirect3DVertexBuffer9::Unlock() { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__); - return m_pWrapped->Unlock(); -} - -HRESULT APIENTRY hkIDirect3DVertexBuffer9::GetDesc(D3DVERTEXBUFFER_DESC *pDesc) { - IDirect3DVertexBuffer9_PrintLog(__FUNCTION__); - return m_pWrapped->GetDesc(pDesc); -} diff --git a/d3d9ex/IDirect3DVertexBuffer9.h b/d3d9ex/IDirect3DVertexBuffer9.h deleted file mode 100644 index 61840c4..0000000 --- a/d3d9ex/IDirect3DVertexBuffer9.h +++ /dev/null @@ -1,42 +0,0 @@ -// wrapper for IDirect3DVertexBuffer9 in d3d9.h -// generated using wrapper_gen.rb - -#pragma once -#include "d3d9.h" - -interface hkIDirect3DVertexBuffer9 final : public IDirect3DVertexBuffer9 { -public: - /*** IUnknown methods ***/ - STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj); - STDMETHOD_(ULONG, AddRef)(THIS); - STDMETHOD_(ULONG, Release)(THIS); - - /*** IDirect3DResource9 methods ***/ - STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice); - STDMETHOD(SetPrivateData)(THIS_ REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags); - STDMETHOD(GetPrivateData)(THIS_ REFGUID refguid, void* pData, DWORD* pSizeOfData); - STDMETHOD(FreePrivateData)(THIS_ REFGUID refguid); - STDMETHOD_(DWORD, SetPriority)(THIS_ DWORD PriorityNew); - STDMETHOD_(DWORD, GetPriority)(THIS); - STDMETHOD_(void, PreLoad)(THIS); - STDMETHOD_(D3DRESOURCETYPE, GetType)(THIS); - STDMETHOD(Lock)(THIS_ UINT OffsetToLock, UINT SizeToLock, void** ppbData, DWORD Flags); - STDMETHOD(Unlock)(THIS); - STDMETHOD(GetDesc)(THIS_ D3DVERTEXBUFFER_DESC* pDesc); - -public: - hkIDirect3DVertexBuffer9(IDirect3DDevice9* pIDirect3DDevice9, IDirect3DVertexBuffer9* pIDirect3DVertexBuffer9) - : m_pWrapped(pIDirect3DVertexBuffer9), m_pIDirect3DDevice9(pIDirect3DDevice9) - {} - -private: - ~hkIDirect3DVertexBuffer9() - { - m_pWrapped->Release(); - } - - LONG m_refCount = 1; - IDirect3DVertexBuffer9 *m_pWrapped; - IDirect3DDevice9* m_pIDirect3DDevice9; -}; - diff --git a/d3d9ex/Settings.h b/d3d9ex/Settings.h index e0231aa..4235097 100644 --- a/d3d9ex/Settings.h +++ b/d3d9ex/Settings.h @@ -1,28 +1,91 @@ +#ifdef SETTING -SETTING(s32, LongValue, PresentationInterval, Options, 1); -SETTING(s32, LongValue, TripleBuffering, Options, -1); -SETTING(s32, LongValue, FullScreenRefreshRate, Options, 0); -SETTING(s32, LongValue, SwapEffect, Options, -1); -SETTING(bool, BoolValue, AlwaysActive, Options, false); -SETTING(bool, BoolValue, AutoFix, Options, true); -SETTING(s32, LongValue, Multisample, Options, 0); -SETTING(bool, BoolValue, HideCursor, Options, false); -SETTING(bool, BoolValue, ForceHideCursor, Options, false); -SETTING(u32, LongValue, BehaviorFlags, Options, 0); +SETTING(s32, LongValue, PresentationInterval, Options, 0, + L"# PresentationInterval (V-Sync)\n" + L"#\n" + L"# -1 = V-Sync forced off\n" + L"# 0 = V-Sync not changed\n" + L"# 1 = V-Sync forced on" +); -SETTING(s32, LongValue, IngameFrameRateLimit, FFXIII, 0); -SETTING(bool, BoolValue, DisableIngameControllerHotSwapping, FFXIII, true); -SETTING(bool, BoolValue, EnableControllerVibration, FFXIII, true); -SETTING(bool, DoubleValue, VibrationStrengthFactor, FFXIII, 2.0); +SETTING(s32, LongValue, TripleBuffering, Options, -1, + L"# TripleBuffering\n" + L"#\n" + L"# -1 = Auto (Disabled for dxvk.dll; else, enabled)\n" + L"# 0 = Off\n" + L"# 1 = On" +); -SETTING(bool, BoolValue, Adapter, Adapter, false); -SETTING(u32, LongValue, VendorId, Adapter, 0); -SETTING(u32, LongValue, DeviceId, Adapter, 0); +SETTING(s32, LongValue, FullScreenRefreshRate, Options, 0, + L"# FullScreenRefreshRate\n" + L"#\n" + L"# If you are not using any adaptive sync technology (e.g. FreeSync/Gsync) you may want to set this to the highest\n" + L"# multiple of your frame rate that your monitor can handle to improve frame pacing.\n" + L"# i.e. if you are using a 60FPS cap, you can possibly improve the frame pacing when you are reaching the cap\n" + L"# by using refresh rates 60, 120, 180, 240...\n" + L"#\n" + L"# 0 = Same as configured in the operating system\n" + L"# other = Use the number provided as the display refresh rate (in Hz)" +); -SETTING(bool, BoolValue, Borderless, Borderless, false); -SETTING(bool, BoolValue, ForceWindowedMode, Borderless, false); -SETTING(bool, BoolValue, AllWindows, Borderless, false); -SETTING(bool, BoolValue, TopMost, Borderless, false); -SETTING(std::wstring, StringValue, WindowClass, Borderless, L""); -SETTING(std::wstring, StringValue, WindowName, Borderless, L""); +SETTING(s32, LongValue, SwapEffect, Options, -1, 0); +SETTING(bool, BoolValue, AlwaysActive, Options, false, 0); +SETTING(bool, BoolValue, AutoFix, Options, true, 0); +SETTING(s32, LongValue, Multisample, Options, 0, 0); +SETTING(bool, BoolValue, HideCursor, Options, false, 0); +SETTING(bool, BoolValue, ForceHideCursor, Options, false, 0); +SETTING(u32, LongValue, BehaviorFlags, Options, 0, 0); +SETTING(s32, LongValue, IngameFrameRateLimit, FFXIII, 0, + L"# IngameFrameRateLimit\n" + L"#\n" + L"# Using higher numbers may cause noticiable facial animation jankness during cutscenes.\n" + L"# See https://github.com/rebtd7/FF13Fix/issues/3\n" + L"#\n" + L"# Note that the frame pacer is always disabled by this mod, regardless of the value this option is set.\n" + L"#\n" + L"# -1 = Use the maximum FPS cap possible\n" + L"# 0 = Use the game's default FPS limit (59.94005966 FPS)\n" + L"# other = Use the number provided as the FPS limit (e.g. set 30 to limit to 30 FPS)" +); +SETTING(bool, BoolValue, DiscardUIVertexBuffer, FFXIII, false, + L"# DiscardUIVertexBuffer (EXPERIMENTAL!)\n" + L"#\n" + L"# Discards UI vertex buffer to improve performance\n" + L"#\n" + L"# false = default, do not hook and discard vertex buffer\n" + L"# true = hook and discard vertex buffer" +); +SETTING(bool, BoolValue, DisableIngameControllerHotSwapping, FFXIII, true, + L"# DisableIngameControllerHotSwapping\n" + L"#\n" + L"# By default FF13Fix disables the game's continuous controller scanning that causes stuttering (especially if you do not have any controller connected)\n" + L"# If you with you can enable it again (by setting the config to 'false', so you can re-connect your controller while playing.\n" + L"# Note that EnableControllerVibration is incompatible with the controller hotswapping, \n" + L"# so it is automatically disabled if DisableIngameControllerHotSwapping is set to 'false'" +); +SETTING(bool, BoolValue, EnableControllerVibration, FFXIII, true, + L"# EnableControllerVibration\n" + L"#\n" + L"# Enables controller vibration on the first connected XInput device." +); +SETTING(bool, DoubleValue, VibrationStrengthFactor, FFXIII, 2.0, + L"# VibrationStrengthFactor\n" + L"#\n" + L"# Higher numbers = stronger vibration" +); + +SETTING(bool, BoolValue, Adapter, Adapter, false, 0); +SETTING(u32, LongValue, VendorId, Adapter, 0, 0); +SETTING(u32, LongValue, DeviceId, Adapter, 0, 0); + +SETTING(bool, BoolValue, TopMost, Window, false, 0); +SETTING(std::wstring, StringValue, WindowClass, Window, L"", 0); +SETTING(std::wstring, StringValue, WindowName, Window, L"", 0); + +SETTING(bool, BoolValue, Borderless, Borderless, false, 0); +SETTING(bool, BoolValue, ForceWindowedMode, Borderless, false, 0); +SETTING(bool, BoolValue, AllWindows, Borderless, false, 0); + + +#endif diff --git a/d3d9ex/VertexFix.cpp b/d3d9ex/VertexFix.cpp new file mode 100644 index 0000000..87595f6 --- /dev/null +++ b/d3d9ex/VertexFix.cpp @@ -0,0 +1,32 @@ +#define CINTERFACE +#include + +#include "Logger.h" +#include "MinHook.h" + +namespace cinterface +{ + HRESULT(STDMETHODCALLTYPE* TrueLock)(IDirect3DVertexBuffer9* This, UINT OffsetToLock, UINT SizeToLock, void** ppbData, DWORD Flags) = nullptr; + + HRESULT STDMETHODCALLTYPE HookLock(IDirect3DVertexBuffer9* This, UINT OffsetToLock, UINT SizeToLock, void** ppbData, DWORD Flags) + { + //PrintLog(__FUNCTION__" %u", SizeToLock); + if (SizeToLock == 358400) + Flags = D3DLOCK_DISCARD; + return TrueLock(This, OffsetToLock, SizeToLock, ppbData, Flags); + } + + void VertexBufferFix(IDirect3DVertexBuffer9* pVertexBuffer) + { + if (pVertexBuffer->lpVtbl->Lock && TrueLock == nullptr) + { + PrintLog("WARINING: Experimental DiscardUIVertexBuffer enabled!"); + const MH_STATUS createHookLock = MH_CreateHook(pVertexBuffer->lpVtbl->Lock, HookLock, reinterpret_cast(&TrueLock)); + PrintLog("CreateHookLock = %d", createHookLock); + const MH_STATUS enableHookLock = MH_EnableHook(pVertexBuffer->lpVtbl->Lock); + PrintLog("EnableHookLock = %d", enableHookLock); + } + } +} + + diff --git a/d3d9ex/Wrapper.h b/d3d9ex/Wrapper.h index 55cddf3..a8fab66 100644 --- a/d3d9ex/Wrapper.h +++ b/d3d9ex/Wrapper.h @@ -1,9 +1,7 @@ #pragma once #include "comdef.h" - -#include "d3d9.h" -#include "xinput.h" +#include template class WrapperBase @@ -104,12 +102,12 @@ private: extern "C" { - IDirect3D9 * WINAPI _Direct3DCreate9(UINT SDKVersion) + IDirect3D9* WINAPI _Direct3DCreate9(UINT SDKVersion) { return D3D9DLL::Get().Direct3DCreate9(SDKVersion); } - HRESULT WINAPI _Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex **ppD3D) + HRESULT WINAPI _Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex** ppD3D) { return D3D9DLL::Get().Direct3DCreate9Ex(SDKVersion, ppD3D); } diff --git a/d3d9ex/d3d9ex.vcxproj b/d3d9ex/d3d9ex.vcxproj index 301bfc4..4c40253 100644 --- a/d3d9ex/d3d9ex.vcxproj +++ b/d3d9ex/d3d9ex.vcxproj @@ -73,7 +73,7 @@ true - dinput8 + d3d9 $(SolutionDir)\Common;$(SolutionDir)\MinHook\include;$(DXSDK_DIR)\Include;$(IncludePath) @@ -98,12 +98,13 @@ Disabled WIN32;_DEBUG;_WINDOWS;_USRDLL;D3D9EX_EXPORTS;%(PreprocessorDefinitions) true + MultiThreadedDebug Windows true exports.def - d3d9.lib;%(AdditionalDependencies) + d3d9.lib;XINPUT9_1_0.LIB;%(AdditionalDependencies) @@ -165,7 +166,6 @@ - @@ -193,15 +193,16 @@ - - true - Create Create Create Create + + NotUsing + NotUsing + diff --git a/d3d9ex/d3d9ex.vcxproj.filters b/d3d9ex/d3d9ex.vcxproj.filters index c6b1ec9..46f8d6f 100644 --- a/d3d9ex/d3d9ex.vcxproj.filters +++ b/d3d9ex/d3d9ex.vcxproj.filters @@ -33,16 +33,13 @@ Header Files - - Header Files - Header Files - + Header Files - + Header Files @@ -65,10 +62,10 @@ Source Files - + Source Files - + Source Files diff --git a/d3d9ex/stdafx.h b/d3d9ex/stdafx.h index ed03828..255159d 100644 --- a/d3d9ex/stdafx.h +++ b/d3d9ex/stdafx.h @@ -24,9 +24,4 @@ #include #include #include -#include - -#include - -#include "WinUtil.h" -#include "Logger.h" \ No newline at end of file +#include \ No newline at end of file