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
This commit is contained in:
Robert Krawczyk 2021-03-13 03:51:58 +01:00
parent d389cc6dec
commit 3a844cc3ca
16 changed files with 348 additions and 321 deletions

View File

@ -5,10 +5,13 @@
#include <memory>
#include <string>
#include <mutex>
#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<std::mutex> lock(Logger::Get().writeMutex());
#endif
va_list args;
va_start(args, format);
Logger::Get().Print(format, args);

View File

@ -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<const MainContext::AutoFixes, const uint32_t> MainContext::behaviorflags_fixes =
const std::map<const MainContext::AutoFixes, const uint32_t> MainContext::behaviorflags_add =
{
};
const std::map<const MainContext::AutoFixes, const uint32_t> 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*>(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<D3DVIEWPORT9*>(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<wchar_t[]>& className)
bool MainContext::OneTimeFixInit(std::unique_ptr<wchar_t[]>& 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<wchar_t[]>& 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<double, std::milli> elapsed = end - start;
PrintLog("Waited %f ms", elapsed.count());
std::lock_guard<std::mutex> 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;
}

View File

@ -1,11 +1,17 @@
#include "stdafx.h"
#include <windows.h>
#include "Wrapper.h"
#include "Context.h"
#include "IDirect3D9.h"
#include <thread>
#include <array>
#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(); }

View File

@ -1,16 +1,13 @@
#pragma once
#include <array>
#include "d3d9.h"
#include <MinHook.h>
#include "SimpleIni.h"
#include "XInputManager.h"
#include "MemPatch.h"
#include <atomic>
#include <d3d9.h>
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<const AutoFixes, const uint32_t> behaviorflags_fixes;
static const std::map<const AutoFixes, const uint32_t> behaviorflags_add;
static const std::map<const AutoFixes, const uint32_t> 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<wchar_t[]>& className);
bool OneTimeFixInit(std::unique_ptr<wchar_t[]>& className);
std::atomic_bool otf_init = false;
static void Fix_Thread();
};

View File

@ -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<IDirect3D9*>(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;
}

View File

@ -1,15 +1,33 @@
// wrapper for IDirect3D9 in d3d9.h
// generated using wrapper_gen.rb
#include "d3d9.h"
#include <d3d9.h>
#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<uint32_t> m_refCount = { 0ul };
std::atomic<uint32_t> 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;
}
}
};

View File

@ -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<IDirect3DDevice9*>(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();

View File

@ -2,21 +2,38 @@
// generated using wrapper_gen.rb
#pragma once
#include "d3d9.h"
#include <d3d9.h>
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<uint32_t> m_refCount = { 0ul };
std::atomic<uint32_t> m_refPrivate = { 1ul };
void AddRefPrivate() {
++m_refPrivate;
}
void ReleasePrivate() {
uint32_t refPrivate = --m_refPrivate;
if (!refPrivate) {
m_refPrivate += 0x80000000;
delete this;
}
}
};

View File

@ -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<IDirect3DVertexBuffer9*>(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);
}

View File

@ -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;
};

View File

@ -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

32
d3d9ex/VertexFix.cpp Normal file
View File

@ -0,0 +1,32 @@
#define CINTERFACE
#include <d3d9.h>
#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<void**>(&TrueLock));
PrintLog("CreateHookLock = %d", createHookLock);
const MH_STATUS enableHookLock = MH_EnableHook(pVertexBuffer->lpVtbl->Lock);
PrintLog("EnableHookLock = %d", enableHookLock);
}
}
}

View File

@ -1,9 +1,7 @@
#pragma once
#include "comdef.h"
#include "d3d9.h"
#include "xinput.h"
#include <d3d9.h>
template <class T>
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);
}

View File

@ -73,7 +73,7 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<TargetName>dinput8</TargetName>
<TargetName>d3d9</TargetName>
<IncludePath>$(SolutionDir)\Common;$(SolutionDir)\MinHook\include;$(DXSDK_DIR)\Include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -98,12 +98,13 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;D3D9EX_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
<AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>d3d9.lib;XINPUT9_1_0.LIB;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -165,7 +166,6 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="Context.h" />
<ClInclude Include="IDirect3DVertexBuffer9.h" />
<ClInclude Include="Wrapper.h" />
<ClInclude Include="IDirect3D9.h" />
<ClInclude Include="IDirect3DDevice9.h" />
@ -193,15 +193,16 @@
</ClCompile>
<ClCompile Include="IDirect3D9.cpp" />
<ClCompile Include="IDirect3DDevice9.cpp" />
<ClCompile Include="IDirect3DVertexBuffer9.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="VertexFix.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="XInputManager.cpp" />
</ItemGroup>
<ItemGroup>

View File

@ -33,16 +33,13 @@
<ClInclude Include="Context.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Settings.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Wrapper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IDirect3DVertexBuffer9.h">
<ClInclude Include="XInputManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="XInputManager.h">
<ClInclude Include="Settings.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
@ -65,10 +62,10 @@
<ClCompile Include="Context.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="IDirect3DVertexBuffer9.cpp">
<ClCompile Include="XInputManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="XInputManager.cpp">
<ClCompile Include="VertexFix.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

View File

@ -24,9 +24,4 @@
#include <array>
#include <vector>
#include <map>
#include <unordered_map>
#include <d3d9.h>
#include "WinUtil.h"
#include "Logger.h"
#include <unordered_map>