diff --git a/CMakeLists.txt b/CMakeLists.txt index f8227ad..0f663b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ endif() list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") include(libzippp) include(minhook) +include(dxtk) add_library(gMod SHARED) @@ -59,10 +60,10 @@ file(GLOB SOURCES ${VERSION_RC} ) -target_include_directories(gMod PRIVATE $ENV{DXSDK_DIR}/Include) -target_include_directories(gMod PUBLIC +target_include_directories(gMod PRIVATE "header" ${CMAKE_INSTALL_PREFIX}/include + $ENV{DXSDK_DIR}/Include ) source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${SOURCES}) target_sources(gMod PRIVATE ${SOURCES}) @@ -74,6 +75,7 @@ target_link_libraries(gMod PRIVATE libzippp psapi minhook + directxtex ) target_link_options(gMod PRIVATE "$<$:/NODEFAULTLIB:LIBCMT>" diff --git a/cmake/dxtk.cmake b/cmake/dxtk.cmake new file mode 100644 index 0000000..bd34913 --- /dev/null +++ b/cmake/dxtk.cmake @@ -0,0 +1,26 @@ +include_guard() +include(FetchContent) + +FetchContent_Declare( + DirectXTex + GIT_REPOSITORY https://github.com/microsoft/DirectXTex + GIT_TAG jul2022) +FetchContent_GetProperties(directxtex) +if (directxtex_POPULATED) + return() +endif() + +FetchContent_Populate(directxtex) + +add_library(directxtex) +set(SOURCES + "${directxtex_SOURCE_DIR}/DDSTextureLoader/DDSTextureLoader9.h" + "${directxtex_SOURCE_DIR}/DDSTextureLoader/DDSTextureLoader9.cpp" + "${directxtex_SOURCE_DIR}/WICTextureLoader/WICTextureLoader9.h" + "${directxtex_SOURCE_DIR}/WICTextureLoader/WICTextureLoader9.cpp" + ) +source_group(TREE ${directxtex_SOURCE_DIR} FILES ${SOURCES}) +target_sources(directxtex PRIVATE ${SOURCES}) +target_include_directories(directxtex PUBLIC "${directxtex_SOURCE_DIR}") + +set_target_properties(directxtex PROPERTIES FOLDER "Dependencies/") diff --git a/header/Defines.h b/header/Defines.h index 707b12b..ca12194 100644 --- a/header/Defines.h +++ b/header/Defines.h @@ -13,3 +13,7 @@ using HashType = DWORD32; #endif #endif + +#ifndef _countof +#define _countof(arr) sizeof(arr) / sizeof(*arr) +#endif diff --git a/header/FileLoader.h b/header/FileLoader.h index 4ddd746..3c2f444 100644 --- a/header/FileLoader.h +++ b/header/FileLoader.h @@ -2,16 +2,8 @@ #include #include -#include #include -struct TpfEntry { - std::string name; - std::string entry; - uint32_t crc_hash; - std::vector data; -}; - class FileLoader { std::string file_name; const std::string TPF_PASSWORD{ @@ -26,13 +18,13 @@ class FileLoader { public: FileLoader(const std::string& fileName); - std::vector GetContents(); + std::vector GetContents(); private: - std::vector GetTpfContents(); + std::vector GetTpfContents(); - std::vector GetFileContents(); + std::vector GetFileContents(); - void LoadEntries(libzippp::ZipArchive& archive, std::vector& entries); + void LoadEntries(libzippp::ZipArchive& archive, std::vector& entries); }; diff --git a/header/Main.h b/header/Main.h index 27b60f8..cda0cc4 100644 --- a/header/Main.h +++ b/header/Main.h @@ -7,7 +7,6 @@ #include "Utils.h" #include -#include #include "Defines.h" #include "Error.h" diff --git a/header/TextureClient.h b/header/TextureClient.h index d5aaa2f..09b4c8d 100644 --- a/header/TextureClient.h +++ b/header/TextureClient.h @@ -4,12 +4,16 @@ #include "FileLoader.h" #include "uMod_IDirect3DTexture9.h" +#include +#include +#include extern unsigned int gl_ErrorState; struct TextureFileStruct { - std::vector data{}; + std::vector data{}; HashType crc_hash = 0; // hash value + bool is_wic_texture = false; }; template @@ -25,7 +29,6 @@ concept uModTexturePtrPtr = uModTexturePtr>; /* * An object of this class is owned by each d3d9 device. - * functions called by the Server are called from the server thread instance. * All other functions are called from the render thread instance of the game itself. */ class TextureClient { @@ -39,9 +42,10 @@ public: // called at the end AddTexture(...) and from Device->UpdateTexture(...) int MergeUpdate(); //called from uMod_IDirect3DDevice9::BeginScene() + void Initialize(); - // Add TpfEntry data, return size of data added. 0 on failure. - unsigned long AddFile(TpfEntry& entry); + // Add TextureFileStruct data, return size of data added. 0 on failure. + unsigned long AddFile(TextureFileStruct& entry); std::vector OriginalTextures; // stores the pointer to the uMod_IDirect3DTexture9 objects created by the game @@ -50,10 +54,6 @@ public: std::vector OriginalCubeTextures; // stores the pointer to the uMod_IDirect3DCubeTexture9 objects created by the game - D3DCOLOR FontColour; - D3DCOLOR TextureColour; - - void Initialize(); private: IDirect3DDevice9* D3D9Device; @@ -72,7 +72,7 @@ private: int LockMutex(); int UnlockMutex(); - HANDLE Mutex; + HANDLE mutex; std::unordered_map modded_textures; // array which stores the file in memory and the hash of each texture to be modded @@ -179,50 +179,63 @@ int TextureClient::LookUpToMod(uModTexturePtr auto pTexture) int TextureClient::LoadTexture(TextureFileStruct* file_in_memory, uModTexturePtrPtr auto ppTexture) { Message("LoadTexture( %p, %p, %#lX): %p\n", file_in_memory, ppTexture, file_in_memory->crc_hash, this); - if constexpr (std::same_as) { - if (D3D_OK != D3DXCreateTextureFromFileInMemoryEx( - D3D9Device, file_in_memory->data.data(), - file_in_memory->data.size(), D3DX_DEFAULT, D3DX_DEFAULT, - D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, - D3DX_DEFAULT, D3DX_DEFAULT, 0, nullptr, nullptr, - (IDirect3DTexture9**)ppTexture)) { - *ppTexture = nullptr; - return RETURN_TEXTURE_NOT_LOADED; + if (file_in_memory->is_wic_texture) { + if constexpr (std::same_as) { + if (D3D_OK != D3DXCreateTextureFromFileInMemoryEx( + D3D9Device, file_in_memory->data.data(), + file_in_memory->data.size(), D3DX_DEFAULT, D3DX_DEFAULT, + D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, + D3DX_DEFAULT, D3DX_DEFAULT, 0, nullptr, nullptr, + reinterpret_cast(ppTexture))) { + *ppTexture = nullptr; + Message("LoadWICTexture( %p, %#lX): FAILED\n", *ppTexture, file_in_memory->crc_hash); + return RETURN_TEXTURE_NOT_LOADED; + } } - SetLastCreatedTexture(nullptr); - } - else if constexpr (std::same_as) { - if (D3D_OK != D3DXCreateVolumeTextureFromFileInMemoryEx( - D3D9Device, file_in_memory->data.data(), - file_in_memory->data.size(), D3DX_DEFAULT, D3DX_DEFAULT, - D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, - D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, - nullptr, - nullptr, - (IDirect3DVolumeTexture9**)ppTexture)) { - *ppTexture = nullptr; - return RETURN_TEXTURE_NOT_LOADED; + else if constexpr (std::same_as) { + if (D3D_OK != D3DXCreateVolumeTextureFromFileInMemoryEx( + D3D9Device, file_in_memory->data.data(), + file_in_memory->data.size(), D3DX_DEFAULT, D3DX_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, + D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, + nullptr, + nullptr, + reinterpret_cast(ppTexture))) { + *ppTexture = nullptr; + Message("LoadWICTexture( %p, %#lX): FAILED\n", *ppTexture, file_in_memory->crc_hash); + return RETURN_TEXTURE_NOT_LOADED; + } + SetLastCreatedVolumeTexture(nullptr); } - SetLastCreatedVolumeTexture(nullptr); - } - else if constexpr (std::same_as) { - if (D3D_OK != D3DXCreateCubeTextureFromFileInMemoryEx( - D3D9Device, file_in_memory->data.data(), file_in_memory->data.size(), D3DX_DEFAULT, D3DX_DEFAULT, 0, - D3DFMT_UNKNOWN, D3DPOOL_MANAGED, - D3DX_DEFAULT, D3DX_DEFAULT, 0, nullptr, nullptr, - (IDirect3DCubeTexture9**)ppTexture)) { - *ppTexture = nullptr; - return RETURN_TEXTURE_NOT_LOADED; + else if constexpr (std::same_as) { + if (D3D_OK != D3DXCreateCubeTextureFromFileInMemoryEx( + D3D9Device, file_in_memory->data.data(), file_in_memory->data.size(), D3DX_DEFAULT, D3DX_DEFAULT, 0, + D3DFMT_UNKNOWN, D3DPOOL_MANAGED, + D3DX_DEFAULT, D3DX_DEFAULT, 0, nullptr, nullptr, + reinterpret_cast(ppTexture))) { + *ppTexture = nullptr; + Message("LoadWICTexture( %p, %#lX): FAILED\n", *ppTexture, file_in_memory->crc_hash); + return RETURN_TEXTURE_NOT_LOADED; + } } - SetLastCreatedCubeTexture(nullptr); } + else if (D3D_OK != DirectX::CreateDDSTextureFromMemoryEx( + D3D9Device, + file_in_memory->data.data(), + file_in_memory->data.size(), + 0, D3DPOOL_MANAGED, false, reinterpret_cast(ppTexture))) { + *ppTexture = nullptr; + Message("LoadDDSTexture( %p, 0x%#lX): FAILED\n", *ppTexture, file_in_memory->crc_hash); + return RETURN_TEXTURE_NOT_LOADED; + } + SetLastCreatedTexture(nullptr); (*ppTexture)->FAKE = true; Message("LoadTexture( %p, %#lX): DONE\n", *ppTexture, file_in_memory->crc_hash); return RETURN_OK; } -template requires uModTexturePtr +template requires uModTexturePtr void UnswitchTextures(T pTexture) { decltype(pTexture) CrossRef = pTexture->CrossRef_D3Dtex; @@ -235,8 +248,8 @@ void UnswitchTextures(T pTexture) } } -template requires uModTexturePtr -inline int SwitchTextures(T pTexture1, T pTexture2) +template requires uModTexturePtr +int SwitchTextures(T pTexture1, T pTexture2) { if (pTexture1->m_D3Ddev == pTexture2->m_D3Ddev && pTexture1->CrossRef_D3Dtex == nullptr && pTexture2->CrossRef_D3Dtex == nullptr) { // make cross reference diff --git a/header/dll_main.h b/header/dll_main.h index 72fa87f..2b0f00d 100644 --- a/header/dll_main.h +++ b/header/dll_main.h @@ -6,5 +6,3 @@ void InitInstance(HINSTANCE hModule); void ExitInstance(); HMODULE LoadOriginalDll(); -IDirect3D9* APIENTRY uMod_Direct3DCreate9(UINT SDKVersion); -HRESULT APIENTRY uMod_Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex** ppD3D); diff --git a/header/uMod_IDirect3DDevice9.h b/header/uMod_IDirect3DDevice9.h index f0eeaa0..a27acec 100644 --- a/header/uMod_IDirect3DDevice9.h +++ b/header/uMod_IDirect3DDevice9.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include "uMod_IDirect3DTexture9.h" #include "uMod_IDirect3DVolumeTexture9.h" #include "uMod_IDirect3DCubeTexture9.h" @@ -178,8 +177,6 @@ private: char SingleTextureMod; D3DCOLOR TextureColour; - ID3DXFont* OSD_Font; - //D3DCOLOR FontColour; int BackBufferCount; bool NormalRendering; diff --git a/header/uMod_IDirect3DDevice9Ex.h b/header/uMod_IDirect3DDevice9Ex.h index 98c72d4..b1ef492 100644 --- a/header/uMod_IDirect3DDevice9Ex.h +++ b/header/uMod_IDirect3DDevice9Ex.h @@ -1,13 +1,12 @@ #pragma once #include -#include + #include "uMod_IDirect3DTexture9.h" #include "uMod_IDirect3DVolumeTexture9.h" #include "uMod_IDirect3DCubeTexture9.h" #include "TextureClient.h" - class uMod_IDirect3DDevice9Ex : public IDirect3DDevice9Ex { public: uMod_IDirect3DDevice9Ex(IDirect3DDevice9Ex* pOriginal, int back_buffer_count); @@ -200,8 +199,6 @@ private: char SingleTextureMod; D3DCOLOR TextureColour; - ID3DXFont* OSD_Font; - //D3DCOLOR FontColour; int BackBufferCount; bool NormalRendering; diff --git a/source/FileLoader.cpp b/source/FileLoader.cpp index cba6b66..2eac11e 100644 --- a/source/FileLoader.cpp +++ b/source/FileLoader.cpp @@ -8,7 +8,7 @@ FileLoader::FileLoader(const std::string& fileName) file_name = std::filesystem::absolute(fileName).string(); } -std::vector FileLoader::GetContents() +std::vector FileLoader::GetContents() { try { return file_name.ends_with(".tpf") ? GetTpfContents() : GetFileContents(); @@ -19,9 +19,9 @@ std::vector FileLoader::GetContents() return {}; } -std::vector FileLoader::GetTpfContents() +std::vector FileLoader::GetTpfContents() { - std::vector entries; + std::vector entries; auto tpf_reader = TpfReader(file_name); const auto buffer = tpf_reader.ReadToEnd(); const auto zip_archive = libzippp::ZipArchive::fromBuffer(buffer.data(), buffer.size(), false, TPF_PASSWORD); @@ -41,9 +41,9 @@ std::vector FileLoader::GetTpfContents() return entries; } -std::vector FileLoader::GetFileContents() +std::vector FileLoader::GetFileContents() { - std::vector entries; + std::vector entries; libzippp::ZipArchive zip_archive(file_name); zip_archive.open(); @@ -53,7 +53,7 @@ std::vector FileLoader::GetFileContents() return entries; } -void ParseSimpleArchive(const libzippp::ZipArchive& archive, std::vector& entries) +void ParseSimpleArchive(const libzippp::ZipArchive& archive, std::vector& entries) { for (const auto& entry : archive.getEntries()) { if (entry.isFile()) { @@ -92,16 +92,17 @@ void ParseSimpleArchive(const libzippp::ZipArchive& archive, std::vector(entry.readAsBinary()); + const auto data_ptr = static_cast(entry.readAsBinary()); const auto size = entry.getSize(); - std::vector vec; - vec.assign(data_ptr, data_ptr + size); - entries.emplace_back(name, entry.getName(), crc_hash, std::move(vec)); + std::vector vec(data_ptr, data_ptr + size); + std::filesystem::path tex_name(entry.getName()); + entries.emplace_back(std::move(vec), crc_hash, tex_name.extension() != ".dds"); + delete[] data_ptr; } } } -void ParseTexmodArchive(std::vector& lines, libzippp::ZipArchive& archive, std::vector& entries) +void ParseTexmodArchive(std::vector& lines, libzippp::ZipArchive& archive, std::vector& entries) { for (const auto& line : lines) { std::istringstream iss(line); @@ -155,17 +156,17 @@ void ParseTexmodArchive(std::vector& lines, libzippp::ZipArchive& a continue; } - const auto data_ptr = static_cast(entry.readAsBinary()); + const auto data_ptr = static_cast(entry.readAsBinary()); const auto size = static_cast(entry.getSize()); std::vector vec(data_ptr, data_ptr + size); - entries.emplace_back(addrstr, entry.getName(), crc_hash, std::move(vec)); + const auto tex_name = std::filesystem::path(entry.getName()); + entries.emplace_back(std::move(vec), crc_hash, tex_name.extension() != ".dds"); delete[] data_ptr; } } -void FileLoader::LoadEntries(libzippp::ZipArchive& archive, std::vector& entries) +void FileLoader::LoadEntries(libzippp::ZipArchive& archive, std::vector& entries) { - // Iterate over the files in the zip archive const auto def_file = archive.getEntry("texmod.def"); if (def_file.isNull() || !def_file.isFile()) { ParseSimpleArchive(archive, entries); diff --git a/source/TextureClient.cpp b/source/TextureClient.cpp index 07ebdbb..855b788 100644 --- a/source/TextureClient.cpp +++ b/source/TextureClient.cpp @@ -11,17 +11,14 @@ TextureClient::TextureClient(IDirect3DDevice9* device) void* cpy; isDirectXExDevice = D3D9Device->QueryInterface(IID_IDirect3DTexture9, &cpy) == 0x01000001L; - Mutex = CreateMutex(nullptr, false, nullptr); - - FontColour = D3DCOLOR_ARGB(255, 255, 0, 0); - TextureColour = D3DCOLOR_ARGB(255, 0, 255, 0); + mutex = CreateMutex(nullptr, false, nullptr); } TextureClient::~TextureClient() { Message("TextureClient::~TextureClient(): %p\n", this); - if (Mutex != nullptr) { - CloseHandle(Mutex); + if (mutex != nullptr) { + CloseHandle(mutex); } for (const auto& it : modded_textures) { delete it.second; @@ -119,7 +116,7 @@ int TextureClient::LockMutex() if ((gl_ErrorState & (uMod_ERROR_FATAL | uMod_ERROR_MUTEX))) { return RETURN_NO_MUTEX; } - if (WAIT_OBJECT_0 != WaitForSingleObject(Mutex, 100)) { + if (WAIT_OBJECT_0 != WaitForSingleObject(mutex, 100)) { return RETURN_MUTEX_LOCK; //waiting 100ms, to wait infinite pass INFINITE } return RETURN_OK; @@ -127,13 +124,13 @@ int TextureClient::LockMutex() int TextureClient::UnlockMutex() { - if (ReleaseMutex(Mutex) == 0) { + if (ReleaseMutex(mutex) == 0) { return RETURN_MUTEX_UNLOCK; } return RETURN_OK; } -unsigned long TextureClient::AddFile(TpfEntry& entry) +unsigned long TextureClient::AddFile(TextureFileStruct& entry) { if (modded_textures.contains(entry.crc_hash)) { return 0; @@ -141,6 +138,7 @@ unsigned long TextureClient::AddFile(TpfEntry& entry) TextureFileStruct* texture_file_struct = new TextureFileStruct(); texture_file_struct->data = std::move(entry.data); texture_file_struct->crc_hash = entry.crc_hash; + texture_file_struct->is_wic_texture = entry.is_wic_texture; modded_textures.emplace(entry.crc_hash, texture_file_struct); should_update = true; return texture_file_struct->data.size(); diff --git a/source/dll_main.cpp b/source/dll_main.cpp index 527fab0..213e8aa 100644 --- a/source/dll_main.cpp +++ b/source/dll_main.cpp @@ -6,6 +6,7 @@ #include #include "MinHook.h" +#include namespace { @@ -20,31 +21,28 @@ namespace { Direct3DCreate9Ex_type Direct3DCreate9Ex_fn = nullptr; Direct3DCreate9Ex_type Direct3DCreate9Ex_ret = nullptr; + static FILE* stdout_proxy; static FILE* stderr_proxy; - /* - * global variable which are linked external - */ - unsigned int gl_ErrorState = 0u; - // If not nullptr, we're responsible for freeing this library on termination - HMODULE gl_hOriginalDll = nullptr; + HMODULE gMod_Loaded_d3d9_Module_Handle = nullptr; // If this hModule called d3d9.dll? - bool IsD3d9Module(HMODULE hModule, HANDLE hProcess) + bool IsD3d9Dll(HMODULE hModule) { TCHAR szModuleName[MAX_PATH]; - GetModuleBaseName(hProcess, hModule, szModuleName, sizeof(szModuleName) / sizeof(TCHAR)); - return strcmp(szModuleName, TEXT("d3d9.dll")) == 0; - } - // Does this module contain exported function calls for creating a d3d9 device? - bool HasD3d9Methods(HMODULE hModule, HANDLE hProcess) - { - return GetProcAddress(hModule, "Direct3DCreate9") - && GetProcAddress(hModule, "Direct3DCreate9Ex"); + ASSERT(GetModuleFileName(hModule, szModuleName, sizeof(szModuleName) / sizeof(*szModuleName)) > 0); + const auto basename = strrchr(szModuleName, '\\'); + return basename && strcmp(basename + 1, "d3d9.dll") == 0; } + // Does this module contain exported function calls for creating a d3d9 device? + bool HasD3d9Methods(HMODULE hModule) + { + return GetProcAddress(hModule, "Direct3DCreate9") + && GetProcAddress(hModule, "Direct3DCreate9Ex"); + } HMODULE FindLoadedDll() { @@ -58,8 +56,9 @@ namespace { if (!EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded)) return nullptr; for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) { - if (IsD3d9Module(hModules[i], hProcess) - || HasD3d9Methods(hModules[i], hProcess)) { + if (hModules[i] == gl_hThisInstance) + continue; + if (IsD3d9Dll(hModules[i])) { return hModules[i]; } } @@ -70,6 +69,36 @@ namespace { unsigned int gl_ErrorState = 0; HINSTANCE gl_hThisInstance = nullptr; +IDirect3D9* APIENTRY Direct3DCreate9(UINT SDKVersion) +{ + Message("uMod_Direct3DCreate9: original %p, uMod %p\n", Direct3DCreate9_fn, Direct3DCreate9); + + ASSERT(Direct3DCreate9_ret); + + IDirect3D9* pIDirect3D9_orig = Direct3DCreate9_ret(SDKVersion); //creating the original IDirect3D9 object + ASSERT(pIDirect3D9_orig); + + return new uMod_IDirect3D9(pIDirect3D9_orig); //return our object instead of the "real one" +} + +HRESULT APIENTRY Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex** ppD3D) +{ + Message("uMod_Direct3DCreate9Ex: original %p, uMod %p\n", Direct3DCreate9Ex_fn, Direct3DCreate9Ex); + + ASSERT(Direct3DCreate9Ex_ret); + + IDirect3D9Ex* pIDirect3D9Ex_orig = nullptr; + HRESULT ret = Direct3DCreate9Ex_ret(SDKVersion, &pIDirect3D9Ex_orig); //creating the original IDirect3D9 object + + if (ret != S_OK) + return ret; + + // @Cleanup: should be we freeing pIDirect3D9Ex at the end of our own lifecycle? + uMod_IDirect3D9Ex* pIDirect3D9Ex = new uMod_IDirect3D9Ex(pIDirect3D9Ex_orig); + ppD3D = (IDirect3D9Ex**)&pIDirect3D9Ex; + return ret; +} + /* * dll entry routine, here we initialize or clean up */ @@ -80,10 +109,10 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserv switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { #ifdef _DEBUG - AllocConsole(); - SetConsoleTitleA("gMod Console"); - freopen_s(&stdout_proxy, "CONOUT$", "w", stdout); - freopen_s(&stderr_proxy, "CONOUT$", "w", stderr); + AllocConsole(); + SetConsoleTitleA("gMod Console"); + freopen_s(&stdout_proxy, "CONOUT$", "w", stdout); + freopen_s(&stderr_proxy, "CONOUT$", "w", stderr); #endif InitInstance(hModule); break; @@ -100,45 +129,47 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserv void InitInstance(HINSTANCE hModule) { - DisableThreadLibraryCalls(hModule); //reduce overhead - gl_hThisInstance = hModule; Message("InitInstance: %p\n", hModule); + DisableThreadLibraryCalls(hModule); //reduce overhead + + // Store the handle to this module + gl_hThisInstance = hModule; const auto d3d9_dll = LoadOriginalDll(); ASSERT(d3d9_dll); - Direct3DCreate9_fn = reinterpret_cast(GetProcAddress(d3d9_dll, "Direct3DCreate9")); - ASSERT(Direct3DCreate9_fn); - - Direct3DCreate9Ex_fn = reinterpret_cast(GetProcAddress(d3d9_dll, "Direct3DCreate9Ex")); - ASSERT(Direct3DCreate9Ex_fn); - MH_Initialize(); + // Hook our loaded Dll's dx9 calls though to uMod's functions + Direct3DCreate9_fn = reinterpret_cast(GetProcAddress(d3d9_dll, "Direct3DCreate9")); + ASSERT(Direct3DCreate9_fn); if (Direct3DCreate9_fn) { - MH_CreateHook(Direct3DCreate9_fn, uMod_Direct3DCreate9, (void**)&Direct3DCreate9_ret); + MH_CreateHook(Direct3DCreate9_fn, Direct3DCreate9, (void**)&Direct3DCreate9_ret); MH_EnableHook(Direct3DCreate9_fn); } + Direct3DCreate9Ex_fn = reinterpret_cast(GetProcAddress(d3d9_dll, "Direct3DCreate9Ex")); + ASSERT(Direct3DCreate9Ex_fn); if (Direct3DCreate9Ex_fn) { - MH_CreateHook(Direct3DCreate9Ex_fn, uMod_Direct3DCreate9Ex, (void**)&Direct3DCreate9Ex_ret); + MH_CreateHook(Direct3DCreate9Ex_fn, Direct3DCreate9Ex, (void**)&Direct3DCreate9Ex_ret); MH_EnableHook(Direct3DCreate9Ex_fn); } } + void ExitInstance() { - if(Direct3DCreate9_fn) + if (Direct3DCreate9_fn) MH_DisableHook(Direct3DCreate9_fn); - if(Direct3DCreate9Ex_fn) + if (Direct3DCreate9Ex_fn) MH_DisableHook(Direct3DCreate9Ex_fn); MH_Uninitialize(); // Release the system's d3d9.dll - if (gl_hOriginalDll != nullptr) { - FreeLibrary(gl_hOriginalDll); - gl_hOriginalDll = nullptr; + if (gMod_Loaded_d3d9_Module_Handle != nullptr) { + ASSERT(FreeLibrary(gMod_Loaded_d3d9_Module_Handle)); + gMod_Loaded_d3d9_Module_Handle = nullptr; } #ifdef _DEBUG @@ -146,7 +177,10 @@ void ExitInstance() fclose(stdout_proxy); if (stderr_proxy) fclose(stderr_proxy); - FreeConsole(); + __try { + FreeConsole(); + } + __except (EXCEPTION_CONTINUE_EXECUTION) { } #endif } @@ -156,14 +190,34 @@ HMODULE LoadOriginalDll() if (found) return found; - char buffer[MAX_PATH]; - GetSystemDirectory(buffer, MAX_PATH); //get the system directory, we need to open the original d3d9.dll + char executable_path[MAX_PATH]{}; + ASSERT(GetModuleFileName(GetModuleHandle(nullptr), executable_path, _countof(executable_path)) > 0); + + char gMod_path[MAX_PATH]{}; + ASSERT(GetModuleFileName(gl_hThisInstance, gMod_path, _countof(gMod_path)) > 0); + + const auto exe_fs_path = std::filesystem::path(executable_path); + const auto gMod_fs_path = std::filesystem::path(gMod_path); + + if (exe_fs_path.parent_path() != gMod_fs_path.parent_path() + || gMod_fs_path.filename() != "d3d9.dll") { + // Call basic LoadLibrary function; we're not in the same directory as the exe. + gMod_Loaded_d3d9_Module_Handle = LoadLibrary("d3d9.dll"); + } + else { + // We're in the same directory as the exe, and we're called 'd3d9.dll'. Calling vanilla "LoadLibrary" will be recursive! + char buffer[MAX_PATH]; + ASSERT(GetSystemDirectory(buffer, _countof(buffer) > 0)); //get the system directory, we need to open the original d3d9.dll + + // Append dll name + strcat_s(buffer, _countof(buffer), "\\d3d9.dll"); + gMod_Loaded_d3d9_Module_Handle = LoadLibrary(buffer); + } + + ASSERT(gMod_Loaded_d3d9_Module_Handle); - // Append dll name - strcat_s(buffer, MAX_PATH, "\\d3d9.dll"); - gl_hOriginalDll = LoadLibrary(buffer); found = FindLoadedDll(); - ASSERT(found && found == gl_hOriginalDll); + ASSERT(found && found == gMod_Loaded_d3d9_Module_Handle); return found; } @@ -171,33 +225,3 @@ HMODULE LoadOriginalDll() /* * We inject the dll into the game, thus we retour the original Direct3DCreate9 function to our MyDirect3DCreate9 function */ - -IDirect3D9* APIENTRY uMod_Direct3DCreate9(UINT SDKVersion) -{ - Message("uMod_Direct3DCreate9: original %p, uMod %p\n", Direct3DCreate9_fn, uMod_Direct3DCreate9); - - ASSERT(Direct3DCreate9_ret); - - IDirect3D9* pIDirect3D9_orig = Direct3DCreate9_ret(SDKVersion); //creating the original IDirect3D9 object - ASSERT(pIDirect3D9_orig); - - return new uMod_IDirect3D9(pIDirect3D9_orig); //return our object instead of the "real one" -} - -HRESULT APIENTRY uMod_Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex** ppD3D) -{ - Message("uMod_Direct3DCreate9Ex: original %p, uMod %p\n", Direct3DCreate9Ex_fn, uMod_Direct3DCreate9Ex); - - ASSERT(Direct3DCreate9Ex_ret); - - IDirect3D9Ex* pIDirect3D9Ex_orig = nullptr; - HRESULT ret = Direct3DCreate9Ex_ret(SDKVersion, &pIDirect3D9Ex_orig); //creating the original IDirect3D9 object - - if (ret != S_OK) - return ret; - - // @Cleanup: should be we freeing pIDirect3D9Ex at the end of our own lifecycle? - uMod_IDirect3D9Ex* pIDirect3D9Ex = new uMod_IDirect3D9Ex(pIDirect3D9Ex_orig); - ppD3D = (IDirect3D9Ex**)&pIDirect3D9Ex; - return ret; -} diff --git a/source/uMod_IDirect3DDevice9.cpp b/source/uMod_IDirect3DDevice9.cpp index 5c537c4..435c0e3 100644 --- a/source/uMod_IDirect3DDevice9.cpp +++ b/source/uMod_IDirect3DDevice9.cpp @@ -11,10 +11,9 @@ int uMod_IDirect3DDevice9::CreateSingleTexture() { - if (SingleTexture != nullptr && SingleVolumeTexture != nullptr && SingleCubeTexture != nullptr && TextureColour == uMod_Client->TextureColour) { + if (SingleTexture != nullptr && SingleVolumeTexture != nullptr && SingleCubeTexture != nullptr) { return RETURN_OK; } - TextureColour = uMod_Client->TextureColour; if (SingleTexture == nullptr) //create texture { if (D3D_OK != CreateTexture(8, 8, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, (IDirect3DTexture9**)&SingleTexture, nullptr)) { @@ -128,7 +127,6 @@ uMod_IDirect3DDevice9::uMod_IDirect3DDevice9(IDirect3DDevice9* pOriginal, int ba SingleTexture = nullptr; SingleVolumeTexture = nullptr; SingleCubeTexture = nullptr; - OSD_Font = nullptr; uMod_Reference = 1; } @@ -181,14 +179,10 @@ ULONG uMod_IDirect3DDevice9::Release() if (SingleCubeTexture != nullptr) { SingleCubeTexture->Release(); //this is the only texture we must release by ourself } - if (OSD_Font != nullptr) { - OSD_Font->Release(); - } delete uMod_Client; //must be deleted at the end, because other releases might call a function of this object uMod_Client = nullptr; SingleTexture = nullptr; - OSD_Font = nullptr; } const ULONG count = m_pIDirect3DDevice9->Release(); @@ -271,10 +265,6 @@ UINT uMod_IDirect3DDevice9::GetNumberOfSwapChains() HRESULT uMod_IDirect3DDevice9::Reset(D3DPRESENT_PARAMETERS* pPresentationParameters) { - if (OSD_Font != nullptr) { - OSD_Font->Release(); - OSD_Font = nullptr; - } //the game will crashes if the font is not released before the game is minimized! return m_pIDirect3DDevice9->Reset(pPresentationParameters); }