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