From 17c7d5bdfcbe817fe791ef36b327fd322196add4 Mon Sep 17 00:00:00 2001 From: henderkes Date: Wed, 3 Jun 2026 22:11:28 +0000 Subject: [PATCH] Replace D3D9 proxy wrappers with vtable hooks --- .clang-format | 48 ++ .github/workflows/lint.yaml | 40 + TpfConvert/src/ModfileLoader.ixx | 9 +- TpfConvert/src/ModfileLoader_TpfReader.ixx | 2 +- TpfConvert/src/TpfConvert.ixx | 4 +- header/D3D9Hooks.h | 18 + header/D3D9State.h | 32 + header/Defines.h | 6 +- header/Error.h | 17 +- header/Main.h | 13 +- header/Utils.h | 8 +- header/uMod_IDirect3D9.h | 31 - header/uMod_IDirect3D9Ex.h | 39 - header/uMod_IDirect3DCubeTexture9.h | 48 -- header/uMod_IDirect3DDevice9.h | 173 ---- header/uMod_IDirect3DDevice9Ex.h | 196 ----- header/uMod_IDirect3DTexture9.h | 48 -- header/uMod_IDirect3DVolumeTexture9.h | 47 -- modules/ModfileLoader.ixx | 10 +- modules/ModfileLoader_TpfReader.ixx | 2 +- modules/TextureClient.ixx | 628 ++++++++------ modules/TextureFunction.ixx | 150 ++-- source/D3D9Hooks.cpp | 560 +++++++++++++ source/Error.cpp | 10 +- source/dll_main.cpp | 55 +- source/uMod_IDirect3D9.cpp | 134 --- source/uMod_IDirect3D9Ex.cpp | 48 -- source/uMod_IDirect3DCubeTexture9.cpp | 283 ------- source/uMod_IDirect3DDevice9.cpp | 914 --------------------- source/uMod_IDirect3DDevice9Ex.cpp | 95 --- source/uMod_IDirect3DTexture9.cpp | 348 -------- source/uMod_IDirect3DVolumeTexture9.cpp | 280 ------- 32 files changed, 1191 insertions(+), 3105 deletions(-) create mode 100644 .clang-format create mode 100644 .github/workflows/lint.yaml create mode 100644 header/D3D9Hooks.h create mode 100644 header/D3D9State.h delete mode 100644 header/uMod_IDirect3D9.h delete mode 100644 header/uMod_IDirect3D9Ex.h delete mode 100644 header/uMod_IDirect3DCubeTexture9.h delete mode 100644 header/uMod_IDirect3DDevice9.h delete mode 100644 header/uMod_IDirect3DDevice9Ex.h delete mode 100644 header/uMod_IDirect3DTexture9.h delete mode 100644 header/uMod_IDirect3DVolumeTexture9.h create mode 100644 source/D3D9Hooks.cpp delete mode 100644 source/uMod_IDirect3D9.cpp delete mode 100644 source/uMod_IDirect3D9Ex.cpp delete mode 100644 source/uMod_IDirect3DCubeTexture9.cpp delete mode 100644 source/uMod_IDirect3DDevice9.cpp delete mode 100644 source/uMod_IDirect3DDevice9Ex.cpp delete mode 100644 source/uMod_IDirect3DTexture9.cpp delete mode 100644 source/uMod_IDirect3DVolumeTexture9.cpp diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..33c0be4 --- /dev/null +++ b/.clang-format @@ -0,0 +1,48 @@ +--- +Language: Cpp +Standard: Latest + +# Long, hand-wrapped declarations (vtable typedefs, D3D signatures) are kept as +# written rather than reflowed to a column. +ColumnLimit: 0 + +IndentWidth: 4 +TabWidth: 4 +UseTab: Never +AccessModifierOffset: -4 +NamespaceIndentation: All +IndentCaseLabels: true +PointerAlignment: Left +MaxEmptyLinesToKeep: 2 +Cpp11BracedListStyle: true +SpaceBeforeParens: ControlStatements +AllowShortCaseLabelsOnASingleLine: true +AllowShortEnumsOnASingleLine: true +FixNamespaceComments: false + +# Include order is load-bearing in the Windows headers; never reorder. +SortIncludes: Never + +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortBlocksOnASingleLine: Always +AllowShortLambdasOnASingleLine: All + +BreakBeforeBraces: Custom +BraceWrapping: + AfterFunction: true + AfterControlStatement: Never + AfterCaseLabel: false + AfterClass: false + AfterStruct: false + AfterEnum: false + AfterUnion: false + AfterNamespace: false + AfterExternBlock: false + BeforeElse: true + BeforeCatch: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 0000000..54a1933 --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,40 @@ +name: gMod Lint + +on: + pull_request: + branches: + - master + push: + branches: + - dev + workflow_dispatch: + +permissions: + contents: write + +jobs: + clang-format: + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref || github.ref_name }} + + # Pinned to the version the tree was formatted with so CI and local agree. + - name: Install clang-format + run: pipx install clang-format==22.1.5 + + - name: Apply clang-format + run: clang-format -i header/*.h source/*.cpp modules/*.ixx TpfConvert/src/*.ixx + + # Push / same-repo PRs: commit the fixes back. Fork PRs can't be pushed to, + # so fail the check instead and let the contributor format. + - name: Commit fixes + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "ci: apply clang-format" + - name: Verify formatting (fork PRs) + if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository + run: git diff --exit-code diff --git a/TpfConvert/src/ModfileLoader.ixx b/TpfConvert/src/ModfileLoader.ixx index 53525b9..707c400 100644 --- a/TpfConvert/src/ModfileLoader.ixx +++ b/TpfConvert/src/ModfileLoader.ixx @@ -13,7 +13,8 @@ export struct TexEntry { }; namespace { - HashType GetCrcFromFilename(const std::string& filename) { + HashType GetCrcFromFilename(const std::string& filename) + { const static std::regex re(R"(0[xX][0-9a-fA-F]{4,16})", std::regex::optimize); std::smatch match; if (!std::regex_search(filename, match, re)) { @@ -45,8 +46,7 @@ export class ModfileLoader { 0x74, 0x61, 0x67, 0x5B, 0x60, 0x70, 0x45, 0x74, 0x5C, 0x22, 0x74, 0x5D, 0x6E, 0x6A, 0x73, 0x41, 0x77, 0x6E, 0x46, 0x47, 0x77, 0x49, 0x0C, 0x4B, - 0x46, 0x6F - }; + 0x46, 0x6F}; public: ModfileLoader(const std::filesystem::path& fileName); @@ -54,7 +54,6 @@ public: std::vector GetContents() const; private: - std::vector GetTpfContents() const; std::vector GetFileContents() const; @@ -85,7 +84,7 @@ std::vector ModfileLoader::GetTpfContents() const const auto buffer = tpf_reader.ReadToEnd(); const auto zip_archive = libzippp::ZipArchive::fromBuffer(buffer.data(), buffer.size(), false, TPF_PASSWORD); if (!zip_archive) { - std::print(stderr, "Failed to open tpf file: {} - {} uint8_ts!\n", file_name.string(), buffer.size()); + std::print(stderr, "Failed to open tpf file: {} - {} uint8_ts!\n", file_name.string(), buffer.size()); return {}; } zip_archive->setErrorHandlerCallback( diff --git a/TpfConvert/src/ModfileLoader_TpfReader.ixx b/TpfConvert/src/ModfileLoader_TpfReader.ixx index 59b9b35..c57c74f 100644 --- a/TpfConvert/src/ModfileLoader_TpfReader.ixx +++ b/TpfConvert/src/ModfileLoader_TpfReader.ixx @@ -35,7 +35,7 @@ public: // in the other zip libraries, these had to be cut off, with libzip we need to zero them out // cutting them off makes the archive invalid - //data.resize(last_zero); + // data.resize(last_zero); return data; } diff --git a/TpfConvert/src/TpfConvert.ixx b/TpfConvert/src/TpfConvert.ixx index cc9a883..5260c6f 100644 --- a/TpfConvert/src/TpfConvert.ixx +++ b/TpfConvert/src/TpfConvert.ixx @@ -27,7 +27,7 @@ namespace { d3dpp.hDeviceWindow = GetDesktopWindow(); if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetDesktopWindow(), - D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice))) { + D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice))) { std::print(stderr, "Failed to create Direct3D9 device\n"); pD3D->Release(); return false; @@ -105,7 +105,7 @@ int main(int argc, char* argv[]) const auto mod_path = modfile.path(); const auto backup_file = backup_path / mod_path.filename(); - if (std::filesystem::exists( backup_file)) { + if (std::filesystem::exists(backup_file)) { std::print("Skipping previous TpfConvert output: {}\n", mod_path.filename().string()); continue; } diff --git a/header/D3D9Hooks.h b/header/D3D9Hooks.h new file mode 100644 index 0000000..feadc6b --- /dev/null +++ b/header/D3D9Hooks.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +// Hooks the IDirect3D9(Ex) CreateDevice slot on the real object returned by +// Direct3DCreate9(Ex); `is_ex` also hooks CreateDeviceEx. Requires a prior +// MH_Initialize() (done in dll_main). +void InstallD3D9Hooks(IDirect3D9* d3d9, bool is_ex); + +// Reverts every gMod hook, leaving the host process as it was. Safe if nothing +// was hooked. +void RemoveAllD3D9Hooks(); + +// Registers a device that already existed when gMod was injected, so the +// CreateDevice hook never ran: hooks its vtable and stands up a TextureClient. +// Textures created from here on are modded; pre-existing ones stay unknown. +// Returns false if the device is null or already registered. +bool RegisterExistingDevice(IDirect3DDevice9* device); diff --git a/header/D3D9State.h b/header/D3D9State.h new file mode 100644 index 0000000..8c9d7ae --- /dev/null +++ b/header/D3D9State.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include "Defines.h" + +// Per-texture side-state, kept in lookups keyed by the real texture pointer (see +// D3D9Hooks.h). Holding it out-of-band leaves the game's own objects untouched, +// so reverting the vtable hooks fully detaches gMod. + +enum class TexType { + Tex2D, + Volume, + Cube, +}; + +// State for one texture: an "original" the game created, or a "fake" we loaded +// from a mod to stand in for one. +struct TexState { + IDirect3DBaseTexture9* real = nullptr; + // An original points at the fake bound in its place (or nullptr); a fake + // points back at the original it replaces. + TexState* partner = nullptr; + IDirect3DDevice9* device = nullptr; + TextureFileStruct* reference = nullptr; // the modfile backing a fake + HashTuple hash = {}; + TexType type = TexType::Tex2D; + bool isFake = false; +}; + +// Content hash (CRC32 + optional CRC64) of an original texture. Defined in +// D3D9Hooks.cpp. +HashTuple GetTextureHash(const TexState* state); diff --git a/header/Defines.h b/header/Defines.h index 5171552..7d566ec 100644 --- a/header/Defines.h +++ b/header/Defines.h @@ -1,6 +1,6 @@ #pragma once -//using HashType = DWORD32; +// using HashType = DWORD32; using HashType = DWORD64; struct HashTuple { @@ -37,7 +37,7 @@ struct TextureFileStruct { inline void Message([[maybe_unused]] const char* format, ...) { #ifdef _DEBUG - //const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + // const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); //[[maybe_unused]] const auto success = SetConsoleTextAttribute(hConsole, 0); // white va_list args; va_start(args, format); @@ -49,7 +49,7 @@ inline void Message([[maybe_unused]] const char* format, ...) inline void Info([[maybe_unused]] const char* format, ...) { #ifdef _DEBUG - //const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + // const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); //[[maybe_unused]] const auto success = SetConsoleTextAttribute(hConsole, 0); // white va_list args; va_start(args, format); diff --git a/header/Error.h b/header/Error.h index 6d43a21..954a71b 100644 --- a/header/Error.h +++ b/header/Error.h @@ -33,14 +33,14 @@ // define error states #define uMod_ERROR_FATAL 1u -#define uMod_ERROR_MUTEX 1u<<1 -#define uMod_ERROR_PIPE 1u<<2 -#define uMod_ERROR_MEMORY 1u<<3 -#define uMod_ERROR_TEXTURE 1u<<4 -#define uMod_ERROR_MULTIPLE_IDirect3D9 1u<<5 -#define uMod_ERROR_MULTIPLE_IDirect3DDevice9 1u<<6 -#define uMod_ERROR_UPDATE 1u<<7 -#define uMod_ERROR_SERVER 1u<<8 +#define uMod_ERROR_MUTEX 1u << 1 +#define uMod_ERROR_PIPE 1u << 2 +#define uMod_ERROR_MEMORY 1u << 3 +#define uMod_ERROR_TEXTURE 1u << 4 +#define uMod_ERROR_MULTIPLE_IDirect3D9 1u << 5 +#define uMod_ERROR_MULTIPLE_IDirect3DDevice9 1u << 6 +#define uMod_ERROR_UPDATE 1u << 7 +#define uMod_ERROR_SERVER 1u << 8 __declspec(noreturn) void FatalAssert( const char* expr, @@ -49,4 +49,3 @@ __declspec(noreturn) void FatalAssert( const char* function); #define ASSERT(expr) ((void)(!!(expr) || (FatalAssert(#expr, __FILE__, (unsigned)__LINE__, __FUNCTION__), 0))) - diff --git a/header/Main.h b/header/Main.h index e45e3a0..c099c07 100644 --- a/header/Main.h +++ b/header/Main.h @@ -16,17 +16,10 @@ #include "Defines.h" #include "Error.h" -#include "Defines.h" -#include "uMod_IDirect3D9.h" -#include "uMod_IDirect3D9Ex.h" - -#include "uMod_IDirect3DDevice9.h" -#include "uMod_IDirect3DDevice9Ex.h" - -#include "uMod_IDirect3DCubeTexture9.h" -#include "uMod_IDirect3DTexture9.h" -#include "uMod_IDirect3DVolumeTexture9.h" +// gMod no longer subclasses the D3D9 interfaces; it hooks their vtable slots and +// keeps per-object side-state in lookups (see D3D9State.h / D3D9Hooks.h). +#include "D3D9State.h" #pragma warning(disable : 4477) diff --git a/header/Utils.h b/header/Utils.h index 2a26c21..518420c 100644 --- a/header/Utils.h +++ b/header/Utils.h @@ -2,9 +2,8 @@ #include -namespace utils -{ - template +namespace utils { + template void erase_first(std::vector& vec, const T& elem) { const auto found = std::ranges::find(vec, elem); @@ -13,7 +12,8 @@ namespace utils } } - inline std::wstring utf8_to_wstring(const std::string& utf8str) { + inline std::wstring utf8_to_wstring(const std::string& utf8str) + { if (utf8str.empty()) return {}; // Calculate the number of wide characters needed for the conversion diff --git a/header/uMod_IDirect3D9.h b/header/uMod_IDirect3D9.h deleted file mode 100644 index 982a70e..0000000 --- a/header/uMod_IDirect3D9.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include - -class uMod_IDirect3D9 : public IDirect3D9 { -public: - uMod_IDirect3D9(IDirect3D9* pOriginal); - virtual ~uMod_IDirect3D9(); - - // The original DX9 function definitions - HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObj) override; - ULONG __stdcall AddRef() override; - ULONG __stdcall Release() override; - HRESULT __stdcall RegisterSoftwareDevice(void* pInitializeFunction) override; - UINT __stdcall GetAdapterCount() override; - HRESULT __stdcall GetAdapterIdentifier(UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) override; - UINT __stdcall GetAdapterModeCount(UINT Adapter, D3DFORMAT Format) override; - HRESULT __stdcall EnumAdapterModes(UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) override; - HRESULT __stdcall GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE* pMode) override; - HRESULT __stdcall CheckDeviceType(UINT iAdapter, D3DDEVTYPE DevType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed) override; - HRESULT __stdcall CheckDeviceFormat(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) override; - HRESULT __stdcall CheckDeviceMultiSampleType(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) override; - HRESULT __stdcall CheckDepthStencilMatch(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) override; - HRESULT __stdcall CheckDeviceFormatConversion(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) override; - HRESULT __stdcall GetDeviceCaps(UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) override; - HMONITOR __stdcall GetAdapterMonitor(UINT Adapter) override; - HRESULT __stdcall CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface) override; - -private: - IDirect3D9* m_pIDirect3D9; -}; diff --git a/header/uMod_IDirect3D9Ex.h b/header/uMod_IDirect3D9Ex.h deleted file mode 100644 index 6692458..0000000 --- a/header/uMod_IDirect3D9Ex.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include - -class uMod_IDirect3D9Ex : public IDirect3D9Ex { -public: - uMod_IDirect3D9Ex(IDirect3D9Ex* pOriginal); - virtual ~uMod_IDirect3D9Ex(); - - // The original DX9 function definitions - HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObj) override; - ULONG __stdcall AddRef() override; - ULONG __stdcall Release() override; - HRESULT __stdcall RegisterSoftwareDevice(void* pInitializeFunction) override; - UINT __stdcall GetAdapterCount() override; - HRESULT __stdcall GetAdapterIdentifier(UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) override; - UINT __stdcall GetAdapterModeCount(UINT Adapter, D3DFORMAT Format) override; - HRESULT __stdcall EnumAdapterModes(UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) override; - HRESULT __stdcall GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE* pMode) override; - HRESULT __stdcall CheckDeviceType(UINT iAdapter, D3DDEVTYPE DevType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed) override; - HRESULT __stdcall CheckDeviceFormat(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) override; - HRESULT __stdcall CheckDeviceMultiSampleType(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) override; - HRESULT __stdcall CheckDepthStencilMatch(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) override; - HRESULT __stdcall CheckDeviceFormatConversion(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) override; - HRESULT __stdcall GetDeviceCaps(UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) override; - HMONITOR __stdcall GetAdapterMonitor(UINT Adapter) override; - HRESULT __stdcall CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface) override; - - HRESULT __stdcall CreateDeviceEx(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode, - IDirect3DDevice9Ex** ppReturnedDeviceInterface) override; - HRESULT __stdcall EnumAdapterModesEx(UINT Adapter, const D3DDISPLAYMODEFILTER* pFilter, UINT Mode, D3DDISPLAYMODEEX* pMode) override; - HRESULT __stdcall GetAdapterDisplayModeEx(UINT Adapter, D3DDISPLAYMODEEX* pMode, D3DDISPLAYROTATION* pRotation) override; - HRESULT __stdcall GetAdapterLUID(UINT Adapter, LUID* pLUID) override; - UINT __stdcall GetAdapterModeCountEx(UINT Adapter, const D3DDISPLAYMODEFILTER* pFilter) override; - -private: - IDirect3D9Ex* m_pIDirect3D9Ex; -}; - diff --git a/header/uMod_IDirect3DCubeTexture9.h b/header/uMod_IDirect3DCubeTexture9.h deleted file mode 100644 index c42f705..0000000 --- a/header/uMod_IDirect3DCubeTexture9.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include - -interface uMod_IDirect3DCubeTexture9 : IDirect3DCubeTexture9 { - uMod_IDirect3DCubeTexture9(IDirect3DCubeTexture9** ppTex, IDirect3DDevice9* pIDirect3DDevice9) - : m_D3Dtex(*ppTex), - m_D3Ddev(pIDirect3DDevice9) - {} - - virtual ~uMod_IDirect3DCubeTexture9() = default; - - // callback interface - IDirect3DCubeTexture9* m_D3Dtex = nullptr; - uMod_IDirect3DCubeTexture9* CrossRef_D3Dtex = nullptr; - IDirect3DDevice9* m_D3Ddev = nullptr; - TextureFileStruct* Reference = nullptr; - HashTuple Hash = {}; - bool FAKE = false; - - // original interface - STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj) override; - STDMETHOD_(ULONG, AddRef)() override; - STDMETHOD_(ULONG, Release)() override; - STDMETHOD(GetDevice)(IDirect3DDevice9** ppDevice) override; - STDMETHOD(SetPrivateData)(REFGUID refguid,CONST void* pData, DWORD SizeOfData, DWORD Flags) override; - STDMETHOD(GetPrivateData)(REFGUID refguid, void* pData, DWORD* pSizeOfData) override; - STDMETHOD(FreePrivateData)(REFGUID refguid) override; - STDMETHOD_(DWORD, SetPriority)(DWORD PriorityNew) override; - STDMETHOD_(DWORD, GetPriority)() override; - STDMETHOD_(void, PreLoad)() override; - STDMETHOD_(D3DRESOURCETYPE, GetType)() override; - STDMETHOD_(DWORD, SetLOD)(DWORD LODNew) override; - STDMETHOD_(DWORD, GetLOD)() override; - STDMETHOD_(DWORD, GetLevelCount)() override; - STDMETHOD(SetAutoGenFilterType)(D3DTEXTUREFILTERTYPE FilterType) override; - STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)() override; - STDMETHOD_(void, GenerateMipSubLevels)() override; - - STDMETHOD(AddDirtyRect)(D3DCUBEMAP_FACES FaceType, CONST RECT* pDirtyRect) override; - STDMETHOD(GetLevelDesc)(UINT Level, D3DSURFACE_DESC* pDesc) override; - STDMETHOD(GetCubeMapSurface)(D3DCUBEMAP_FACES FaceType, UINT Level, IDirect3DSurface9** ppCubeMapSurface) override; - STDMETHOD(LockRect)(D3DCUBEMAP_FACES FaceType, UINT Level, D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect, DWORD Flags) override; - STDMETHOD(UnlockRect)(D3DCUBEMAP_FACES FaceType, UINT Level) override; - - - [[nodiscard]] HashTuple GetHash() const; -}; diff --git a/header/uMod_IDirect3DDevice9.h b/header/uMod_IDirect3DDevice9.h deleted file mode 100644 index 634c1b9..0000000 --- a/header/uMod_IDirect3DDevice9.h +++ /dev/null @@ -1,173 +0,0 @@ -#pragma once - -#include -#include "uMod_IDirect3DTexture9.h" -#include "uMod_IDirect3DVolumeTexture9.h" -#include "uMod_IDirect3DCubeTexture9.h" - -class TextureClient; - -class uMod_IDirect3DDevice9 : public IDirect3DDevice9 { -public: - uMod_IDirect3DDevice9(IDirect3DDevice9* pOriginal, int back_buffer_count); - virtual ~uMod_IDirect3DDevice9(); - - // START: The original DX9 function definitions - HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObj) override; - ULONG __stdcall AddRef() override; - ULONG __stdcall Release() override; - HRESULT __stdcall TestCooperativeLevel() override; - UINT __stdcall GetAvailableTextureMem() override; - HRESULT __stdcall EvictManagedResources() override; - HRESULT __stdcall GetDirect3D(IDirect3D9** ppD3D9) override; - HRESULT __stdcall GetDeviceCaps(D3DCAPS9* pCaps) override; - HRESULT __stdcall GetDisplayMode(UINT iSwapChain, D3DDISPLAYMODE* pMode) override; - HRESULT __stdcall GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS* pParameters) override; - HRESULT __stdcall SetCursorProperties(UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap) override; - void __stdcall SetCursorPosition(int X, int Y, DWORD Flags) override; - BOOL __stdcall ShowCursor(BOOL bShow) override; - HRESULT __stdcall CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain) override; - HRESULT __stdcall GetSwapChain(UINT iSwapChain, IDirect3DSwapChain9** pSwapChain) override; - UINT __stdcall GetNumberOfSwapChains() override; - HRESULT __stdcall Reset(D3DPRESENT_PARAMETERS* pPresentationParameters) override; - HRESULT __stdcall Present(CONST RECT* pSourceRect,CONST RECT* pDestRect, HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) override; - HRESULT __stdcall GetBackBuffer(UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) override; - HRESULT __stdcall GetRasterStatus(UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) override; - HRESULT __stdcall SetDialogBoxMode(BOOL bEnableDialogs) override; - void __stdcall SetGammaRamp(UINT iSwapChain, DWORD Flags,CONST D3DGAMMARAMP* pRamp) override; - void __stdcall GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP* pRamp) override; - HRESULT __stdcall CreateTexture(UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle) override; - HRESULT __stdcall CreateVolumeTexture(UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) override; - HRESULT __stdcall CreateCubeTexture(UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) override; - HRESULT __stdcall CreateVertexBuffer(UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle) override; - HRESULT __stdcall CreateIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle) override; - HRESULT __stdcall CreateRenderTarget(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) override; - HRESULT __stdcall CreateDepthStencilSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) override; - HRESULT __stdcall UpdateSurface(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect, IDirect3DSurface9* pDestinationSurface,CONST POINT* pDestPoint) override; - HRESULT __stdcall UpdateTexture(IDirect3DBaseTexture9* pSourceTexture, IDirect3DBaseTexture9* pDestinationTexture) override; - HRESULT __stdcall GetRenderTargetData(IDirect3DSurface9* pRenderTarget, IDirect3DSurface9* pDestSurface) override; - HRESULT __stdcall GetFrontBufferData(UINT iSwapChain, IDirect3DSurface9* pDestSurface) override; - HRESULT __stdcall StretchRect(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) override; - HRESULT __stdcall ColorFill(IDirect3DSurface9* pSurface,CONST RECT* pRect, D3DCOLOR color) override; - HRESULT __stdcall CreateOffscreenPlainSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) override; - HRESULT __stdcall SetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) override; - HRESULT __stdcall GetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9** ppRenderTarget) override; - HRESULT __stdcall SetDepthStencilSurface(IDirect3DSurface9* pNewZStencil) override; - HRESULT __stdcall GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface) override; - HRESULT __stdcall BeginScene() override; - HRESULT __stdcall EndScene() override; - HRESULT __stdcall Clear(DWORD Count,CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) override; - HRESULT __stdcall SetTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) override; - HRESULT __stdcall GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) override; - HRESULT __stdcall MultiplyTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) override; - HRESULT __stdcall SetViewport(CONST D3DVIEWPORT9* pViewport) override; - HRESULT __stdcall GetViewport(D3DVIEWPORT9* pViewport) override; - HRESULT __stdcall SetMaterial(CONST D3DMATERIAL9* pMaterial) override; - HRESULT __stdcall GetMaterial(D3DMATERIAL9* pMaterial) override; - HRESULT __stdcall SetLight(DWORD Index,CONST D3DLIGHT9* pLight) override; - HRESULT __stdcall GetLight(DWORD Index, D3DLIGHT9* pLight) override; - HRESULT __stdcall LightEnable(DWORD Index, BOOL Enable) override; - HRESULT __stdcall GetLightEnable(DWORD Index, BOOL* pEnable) override; - HRESULT __stdcall SetClipPlane(DWORD Index,CONST float* pPlane) override; - HRESULT __stdcall GetClipPlane(DWORD Index, float* pPlane) override; - HRESULT __stdcall SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) override; - HRESULT __stdcall GetRenderState(D3DRENDERSTATETYPE State, DWORD* pValue) override; - HRESULT __stdcall CreateStateBlock(D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9** ppSB) override; - HRESULT __stdcall BeginStateBlock() override; - HRESULT __stdcall EndStateBlock(IDirect3DStateBlock9** ppSB) override; - HRESULT __stdcall SetClipStatus(CONST D3DCLIPSTATUS9* pClipStatus) override; - HRESULT __stdcall GetClipStatus(D3DCLIPSTATUS9* pClipStatus) override; - HRESULT __stdcall GetTexture(DWORD Stage, IDirect3DBaseTexture9** ppTexture) override; - HRESULT __stdcall SetTexture(DWORD Stage, IDirect3DBaseTexture9* pTexture) override; - HRESULT __stdcall GetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) override; - HRESULT __stdcall SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) override; - HRESULT __stdcall GetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) override; - HRESULT __stdcall SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) override; - HRESULT __stdcall ValidateDevice(DWORD* pNumPasses) override; - HRESULT __stdcall SetPaletteEntries(UINT PaletteNumber,CONST PALETTEENTRY* pEntries) override; - HRESULT __stdcall GetPaletteEntries(UINT PaletteNumber, PALETTEENTRY* pEntries) override; - HRESULT __stdcall SetCurrentTexturePalette(UINT PaletteNumber) override; - HRESULT __stdcall GetCurrentTexturePalette(UINT* PaletteNumber) override; - HRESULT __stdcall SetScissorRect(CONST RECT* pRect) override; - HRESULT __stdcall GetScissorRect(RECT* pRect) override; - HRESULT __stdcall SetSoftwareVertexProcessing(BOOL bSoftware) override; - BOOL __stdcall GetSoftwareVertexProcessing() override; - HRESULT __stdcall SetNPatchMode(float nSegments) override; - float __stdcall GetNPatchMode() override; - HRESULT __stdcall DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) override; - HRESULT __stdcall DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) override; - HRESULT __stdcall DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount,CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) override; - HRESULT __stdcall DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, UINT PrimitiveCount,CONST void* pIndexData, D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData, - UINT VertexStreamZeroStride) override; - HRESULT __stdcall ProcessVertices(UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) override; - HRESULT __stdcall CreateVertexDeclaration(CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) override; - HRESULT __stdcall SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl) override; - HRESULT __stdcall GetVertexDeclaration(IDirect3DVertexDeclaration9** ppDecl) override; - HRESULT __stdcall SetFVF(DWORD FVF) override; - HRESULT __stdcall GetFVF(DWORD* pFVF) override; - HRESULT __stdcall CreateVertexShader(CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader) override; - HRESULT __stdcall SetVertexShader(IDirect3DVertexShader9* pShader) override; - HRESULT __stdcall GetVertexShader(IDirect3DVertexShader9** ppShader) override; - HRESULT __stdcall SetVertexShaderConstantF(UINT StartRegister,CONST float* pConstantData, UINT Vector4fCount) override; - HRESULT __stdcall GetVertexShaderConstantF(UINT StartRegister, float* pConstantData, UINT Vector4fCount) override; - HRESULT __stdcall SetVertexShaderConstantI(UINT StartRegister,CONST int* pConstantData, UINT Vector4iCount) override; - HRESULT __stdcall GetVertexShaderConstantI(UINT StartRegister, int* pConstantData, UINT Vector4iCount) override; - HRESULT __stdcall SetVertexShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData, UINT BoolCount) override; - HRESULT __stdcall GetVertexShaderConstantB(UINT StartRegister, BOOL* pConstantData, UINT BoolCount) override; - HRESULT __stdcall SetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride) override; - HRESULT __stdcall GetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* OffsetInBytes, UINT* pStride) override; - HRESULT __stdcall SetStreamSourceFreq(UINT StreamNumber, UINT Divider) override; - HRESULT __stdcall GetStreamSourceFreq(UINT StreamNumber, UINT* Divider) override; - HRESULT __stdcall SetIndices(IDirect3DIndexBuffer9* pIndexData) override; - HRESULT __stdcall GetIndices(IDirect3DIndexBuffer9** ppIndexData) override; - HRESULT __stdcall CreatePixelShader(CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader) override; - HRESULT __stdcall SetPixelShader(IDirect3DPixelShader9* pShader) override; - HRESULT __stdcall GetPixelShader(IDirect3DPixelShader9** ppShader) override; - HRESULT __stdcall SetPixelShaderConstantF(UINT StartRegister,CONST float* pConstantData, UINT Vector4fCount) override; - HRESULT __stdcall GetPixelShaderConstantF(UINT StartRegister, float* pConstantData, UINT Vector4fCount) override; - HRESULT __stdcall SetPixelShaderConstantI(UINT StartRegister,CONST int* pConstantData, UINT Vector4iCount) override; - HRESULT __stdcall GetPixelShaderConstantI(UINT StartRegister, int* pConstantData, UINT Vector4iCount) override; - HRESULT __stdcall SetPixelShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData, UINT BoolCount) override; - HRESULT __stdcall GetPixelShaderConstantB(UINT StartRegister, BOOL* pConstantData, UINT BoolCount) override; - HRESULT __stdcall DrawRectPatch(UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) override; - HRESULT __stdcall DrawTriPatch(UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) override; - HRESULT __stdcall DeletePatch(UINT Handle) override; - HRESULT __stdcall CreateQuery(D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) override; - // END: The original DX9 function definitions - - TextureClient* GetuMod_Client() { return uMod_Client; } - - uMod_IDirect3DTexture9* GetLastCreatedTexture() { return LastCreatedTexture; } - - void SetLastCreatedTexture(uMod_IDirect3DTexture9* pTexture) - { - LastCreatedTexture = pTexture; - } - - uMod_IDirect3DVolumeTexture9* GetLastCreatedVolumeTexture() { return LastCreatedVolumeTexture; } - - void SetLastCreatedVolumeTexture(uMod_IDirect3DVolumeTexture9* pTexture) - { - LastCreatedVolumeTexture = pTexture; - } - - uMod_IDirect3DCubeTexture9* GetLastCreatedCubeTexture() { return LastCreatedCubeTexture; } - - void SetLastCreatedCubeTexture(uMod_IDirect3DCubeTexture9* pTexture) - { - LastCreatedCubeTexture = pTexture; - } - -private: - IDirect3DDevice9* m_pIDirect3DDevice9 = nullptr; - - int BackBufferCount; - bool NormalRendering = true; - int uMod_Reference = 1; - - uMod_IDirect3DTexture9* LastCreatedTexture = nullptr; - uMod_IDirect3DVolumeTexture9* LastCreatedVolumeTexture = nullptr; - uMod_IDirect3DCubeTexture9* LastCreatedCubeTexture = nullptr; - - TextureClient* uMod_Client; -}; diff --git a/header/uMod_IDirect3DDevice9Ex.h b/header/uMod_IDirect3DDevice9Ex.h deleted file mode 100644 index a678d06..0000000 --- a/header/uMod_IDirect3DDevice9Ex.h +++ /dev/null @@ -1,196 +0,0 @@ -#pragma once - -#include -#include "uMod_IDirect3DTexture9.h" -#include "uMod_IDirect3DVolumeTexture9.h" -#include "uMod_IDirect3DCubeTexture9.h" - -class TextureClient; - -class uMod_IDirect3DDevice9Ex : public IDirect3DDevice9Ex { -public: - uMod_IDirect3DDevice9Ex(IDirect3DDevice9Ex* pOriginal, int back_buffer_count); - virtual ~uMod_IDirect3DDevice9Ex(); - - // START: The original DX9 function definitions - HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObj) override; - ULONG __stdcall AddRef() override; - ULONG __stdcall Release() override; - HRESULT __stdcall TestCooperativeLevel() override; - UINT __stdcall GetAvailableTextureMem() override; - HRESULT __stdcall EvictManagedResources() override; - HRESULT __stdcall GetDirect3D(IDirect3D9** ppD3D9) override; - HRESULT __stdcall GetDeviceCaps(D3DCAPS9* pCaps) override; - HRESULT __stdcall GetDisplayMode(UINT iSwapChain, D3DDISPLAYMODE* pMode) override; - HRESULT __stdcall GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS* pParameters) override; - HRESULT __stdcall SetCursorProperties(UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap) override; - void __stdcall SetCursorPosition(int X, int Y, DWORD Flags) override; - BOOL __stdcall ShowCursor(BOOL bShow) override; - HRESULT __stdcall CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain) override; - HRESULT __stdcall GetSwapChain(UINT iSwapChain, IDirect3DSwapChain9** pSwapChain) override; - UINT __stdcall GetNumberOfSwapChains() override; - HRESULT __stdcall Reset(D3DPRESENT_PARAMETERS* pPresentationParameters) override; - HRESULT __stdcall Present(CONST RECT* pSourceRect,CONST RECT* pDestRect, HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) override; - HRESULT __stdcall GetBackBuffer(UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) override; - HRESULT __stdcall GetRasterStatus(UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) override; - HRESULT __stdcall SetDialogBoxMode(BOOL bEnableDialogs) override; - void __stdcall SetGammaRamp(UINT iSwapChain, DWORD Flags,CONST D3DGAMMARAMP* pRamp) override; - void __stdcall GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP* pRamp) override; - HRESULT __stdcall CreateTexture(UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle) override; - HRESULT __stdcall CreateVolumeTexture(UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) override; - HRESULT __stdcall CreateCubeTexture(UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) override; - HRESULT __stdcall CreateVertexBuffer(UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle) override; - HRESULT __stdcall CreateIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle) override; - HRESULT __stdcall CreateRenderTarget(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) override; - HRESULT __stdcall CreateDepthStencilSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) override; - HRESULT __stdcall UpdateSurface(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect, IDirect3DSurface9* pDestinationSurface,CONST POINT* pDestPoint) override; - HRESULT __stdcall UpdateTexture(IDirect3DBaseTexture9* pSourceTexture, IDirect3DBaseTexture9* pDestinationTexture) override; - HRESULT __stdcall GetRenderTargetData(IDirect3DSurface9* pRenderTarget, IDirect3DSurface9* pDestSurface) override; - HRESULT __stdcall GetFrontBufferData(UINT iSwapChain, IDirect3DSurface9* pDestSurface) override; - HRESULT __stdcall StretchRect(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) override; - HRESULT __stdcall ColorFill(IDirect3DSurface9* pSurface,CONST RECT* pRect, D3DCOLOR color) override; - HRESULT __stdcall CreateOffscreenPlainSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) override; - HRESULT __stdcall SetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) override; - HRESULT __stdcall GetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9** ppRenderTarget) override; - HRESULT __stdcall SetDepthStencilSurface(IDirect3DSurface9* pNewZStencil) override; - HRESULT __stdcall GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface) override; - HRESULT __stdcall BeginScene() override; - HRESULT __stdcall EndScene() override; - HRESULT __stdcall Clear(DWORD Count,CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) override; - HRESULT __stdcall SetTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) override; - HRESULT __stdcall GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) override; - HRESULT __stdcall MultiplyTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) override; - HRESULT __stdcall SetViewport(CONST D3DVIEWPORT9* pViewport) override; - HRESULT __stdcall GetViewport(D3DVIEWPORT9* pViewport) override; - HRESULT __stdcall SetMaterial(CONST D3DMATERIAL9* pMaterial) override; - HRESULT __stdcall GetMaterial(D3DMATERIAL9* pMaterial) override; - HRESULT __stdcall SetLight(DWORD Index,CONST D3DLIGHT9* pLight) override; - HRESULT __stdcall GetLight(DWORD Index, D3DLIGHT9* pLight) override; - HRESULT __stdcall LightEnable(DWORD Index, BOOL Enable) override; - HRESULT __stdcall GetLightEnable(DWORD Index, BOOL* pEnable) override; - HRESULT __stdcall SetClipPlane(DWORD Index,CONST float* pPlane) override; - HRESULT __stdcall GetClipPlane(DWORD Index, float* pPlane) override; - HRESULT __stdcall SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) override; - HRESULT __stdcall GetRenderState(D3DRENDERSTATETYPE State, DWORD* pValue) override; - HRESULT __stdcall CreateStateBlock(D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9** ppSB) override; - HRESULT __stdcall BeginStateBlock() override; - HRESULT __stdcall EndStateBlock(IDirect3DStateBlock9** ppSB) override; - HRESULT __stdcall SetClipStatus(CONST D3DCLIPSTATUS9* pClipStatus) override; - HRESULT __stdcall GetClipStatus(D3DCLIPSTATUS9* pClipStatus) override; - HRESULT __stdcall GetTexture(DWORD Stage, IDirect3DBaseTexture9** ppTexture) override; - HRESULT __stdcall SetTexture(DWORD Stage, IDirect3DBaseTexture9* pTexture) override; - HRESULT __stdcall GetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) override; - HRESULT __stdcall SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) override; - HRESULT __stdcall GetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) override; - HRESULT __stdcall SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) override; - HRESULT __stdcall ValidateDevice(DWORD* pNumPasses) override; - HRESULT __stdcall SetPaletteEntries(UINT PaletteNumber,CONST PALETTEENTRY* pEntries) override; - HRESULT __stdcall GetPaletteEntries(UINT PaletteNumber, PALETTEENTRY* pEntries) override; - HRESULT __stdcall SetCurrentTexturePalette(UINT PaletteNumber) override; - HRESULT __stdcall GetCurrentTexturePalette(UINT* PaletteNumber) override; - HRESULT __stdcall SetScissorRect(CONST RECT* pRect) override; - HRESULT __stdcall GetScissorRect(RECT* pRect) override; - HRESULT __stdcall SetSoftwareVertexProcessing(BOOL bSoftware) override; - BOOL __stdcall GetSoftwareVertexProcessing() override; - HRESULT __stdcall SetNPatchMode(float nSegments) override; - float __stdcall GetNPatchMode() override; - HRESULT __stdcall DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) override; - HRESULT __stdcall DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) override; - HRESULT __stdcall DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount,CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) override; - HRESULT __stdcall DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, UINT PrimitiveCount,CONST void* pIndexData, D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData, - UINT VertexStreamZeroStride) override; - HRESULT __stdcall ProcessVertices(UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) override; - HRESULT __stdcall CreateVertexDeclaration(CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) override; - HRESULT __stdcall SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl) override; - HRESULT __stdcall GetVertexDeclaration(IDirect3DVertexDeclaration9** ppDecl) override; - HRESULT __stdcall SetFVF(DWORD FVF) override; - HRESULT __stdcall GetFVF(DWORD* pFVF) override; - HRESULT __stdcall CreateVertexShader(CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader) override; - HRESULT __stdcall SetVertexShader(IDirect3DVertexShader9* pShader) override; - HRESULT __stdcall GetVertexShader(IDirect3DVertexShader9** ppShader) override; - HRESULT __stdcall SetVertexShaderConstantF(UINT StartRegister,CONST float* pConstantData, UINT Vector4fCount) override; - HRESULT __stdcall GetVertexShaderConstantF(UINT StartRegister, float* pConstantData, UINT Vector4fCount) override; - HRESULT __stdcall SetVertexShaderConstantI(UINT StartRegister,CONST int* pConstantData, UINT Vector4iCount) override; - HRESULT __stdcall GetVertexShaderConstantI(UINT StartRegister, int* pConstantData, UINT Vector4iCount) override; - HRESULT __stdcall SetVertexShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData, UINT BoolCount) override; - HRESULT __stdcall GetVertexShaderConstantB(UINT StartRegister, BOOL* pConstantData, UINT BoolCount) override; - HRESULT __stdcall SetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride) override; - HRESULT __stdcall GetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* OffsetInBytes, UINT* pStride) override; - HRESULT __stdcall SetStreamSourceFreq(UINT StreamNumber, UINT Divider) override; - HRESULT __stdcall GetStreamSourceFreq(UINT StreamNumber, UINT* Divider) override; - HRESULT __stdcall SetIndices(IDirect3DIndexBuffer9* pIndexData) override; - HRESULT __stdcall GetIndices(IDirect3DIndexBuffer9** ppIndexData) override; - HRESULT __stdcall CreatePixelShader(CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader) override; - HRESULT __stdcall SetPixelShader(IDirect3DPixelShader9* pShader) override; - HRESULT __stdcall GetPixelShader(IDirect3DPixelShader9** ppShader) override; - HRESULT __stdcall SetPixelShaderConstantF(UINT StartRegister,CONST float* pConstantData, UINT Vector4fCount) override; - HRESULT __stdcall GetPixelShaderConstantF(UINT StartRegister, float* pConstantData, UINT Vector4fCount) override; - HRESULT __stdcall SetPixelShaderConstantI(UINT StartRegister,CONST int* pConstantData, UINT Vector4iCount) override; - HRESULT __stdcall GetPixelShaderConstantI(UINT StartRegister, int* pConstantData, UINT Vector4iCount) override; - HRESULT __stdcall SetPixelShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData, UINT BoolCount) override; - HRESULT __stdcall GetPixelShaderConstantB(UINT StartRegister, BOOL* pConstantData, UINT BoolCount) override; - HRESULT __stdcall DrawRectPatch(UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) override; - HRESULT __stdcall DrawTriPatch(UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) override; - HRESULT __stdcall DeletePatch(UINT Handle) override; - HRESULT __stdcall CreateQuery(D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) override; - - - - HRESULT __stdcall CheckDeviceState(HWND hWindow) override; - HRESULT __stdcall CheckResourceResidency(IDirect3DResource9** pResourceArray, UINT32 NumResources) override; - HRESULT __stdcall ComposeRects(IDirect3DSurface9* pSource, IDirect3DSurface9* pDestination, IDirect3DVertexBuffer9* pSrcRectDescriptors, UINT NumRects, IDirect3DVertexBuffer9* pDstRectDescriptors, D3DCOMPOSERECTSOP Operation, INT XOffset, - INT YOffset) override; - HRESULT __stdcall CreateDepthStencilSurfaceEx(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle, DWORD Usage) override; - HRESULT __stdcall CreateOffscreenPlainSurfaceEx(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle, DWORD Usage) override; - HRESULT __stdcall CreateRenderTargetEx(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle, DWORD Usage) override; - HRESULT __stdcall GetDisplayModeEx(UINT iSwapChain, D3DDISPLAYMODEEX* pMode, D3DDISPLAYROTATION* pRotation) override; - HRESULT __stdcall GetGPUThreadPriority(INT* pPriority) override; - HRESULT __stdcall GetMaximumFrameLatency(UINT* pMaxLatency) override; - HRESULT __stdcall PresentEx(const RECT* pSourceRect, const RECT* pDestRect, HWND hDestWindowOverride, const RGNDATA* pDirtyRegion, DWORD dwFlags) override; - HRESULT __stdcall ResetEx(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode) override; - HRESULT __stdcall SetConvolutionMonoKernel(UINT Width, UINT Height, float* RowWeights, float* ColumnWeights) override; - HRESULT __stdcall SetGPUThreadPriority(INT pPriority) override; - HRESULT __stdcall SetMaximumFrameLatency(UINT pMaxLatency) override; - //HRESULT __stdcall TestCooperativeLevel(); - HRESULT __stdcall WaitForVBlank(UINT SwapChainIndex) override; - - - // END: The original DX9 function definitions - - TextureClient* GetuMod_Client() { return uMod_Client; } - - uMod_IDirect3DTexture9* GetLastCreatedTexture() { return LastCreatedTexture; } - - void SetLastCreatedTexture(uMod_IDirect3DTexture9* pTexture) - { - LastCreatedTexture = pTexture; - } - - uMod_IDirect3DVolumeTexture9* GetLastCreatedVolumeTexture() { return LastCreatedVolumeTexture; } - - void SetLastCreatedVolumeTexture(uMod_IDirect3DVolumeTexture9* pTexture) - { - LastCreatedVolumeTexture = pTexture; - } - - uMod_IDirect3DCubeTexture9* GetLastCreatedCubeTexture() { return LastCreatedCubeTexture; } - - void SetLastCreatedCubeTexture(uMod_IDirect3DCubeTexture9* pTexture) - { - LastCreatedCubeTexture = pTexture; - } - -private: - IDirect3DDevice9Ex* m_pIDirect3DDevice9Ex; - - int BackBufferCount; - bool NormalRendering = true; - - int uMod_Reference = 1; - - uMod_IDirect3DTexture9* LastCreatedTexture = nullptr; - uMod_IDirect3DVolumeTexture9* LastCreatedVolumeTexture = nullptr; - uMod_IDirect3DCubeTexture9* LastCreatedCubeTexture = nullptr; - - TextureClient* uMod_Client = nullptr; -}; diff --git a/header/uMod_IDirect3DTexture9.h b/header/uMod_IDirect3DTexture9.h deleted file mode 100644 index 544805e..0000000 --- a/header/uMod_IDirect3DTexture9.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include -#include "Defines.h" - -struct TextureFileStruct; -interface uMod_IDirect3DTexture9 : IDirect3DTexture9 { - uMod_IDirect3DTexture9(IDirect3DTexture9** ppTex, IDirect3DDevice9* pIDirect3DDevice9) - : m_D3Dtex(*ppTex), - m_D3Ddev(pIDirect3DDevice9) - {} - - virtual ~uMod_IDirect3DTexture9() = default; - - // callback interface - IDirect3DTexture9* m_D3Dtex = nullptr; - uMod_IDirect3DTexture9* CrossRef_D3Dtex = nullptr; - IDirect3DDevice9* m_D3Ddev = nullptr; - TextureFileStruct* Reference = nullptr; - HashTuple Hash = {}; - bool FAKE = false; - - // original interface - STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj) override; - STDMETHOD_(ULONG, AddRef)() override; - STDMETHOD_(ULONG, Release)() override; - STDMETHOD(GetDevice)(IDirect3DDevice9** ppDevice) override; - STDMETHOD(SetPrivateData)(REFGUID refguid,CONST void* pData, DWORD SizeOfData, DWORD Flags) override; - STDMETHOD(GetPrivateData)(REFGUID refguid, void* pData, DWORD* pSizeOfData) override; - STDMETHOD(FreePrivateData)(REFGUID refguid) override; - STDMETHOD_(DWORD, SetPriority)(DWORD PriorityNew) override; - STDMETHOD_(DWORD, GetPriority)() override; - STDMETHOD_(void, PreLoad)() override; - STDMETHOD_(D3DRESOURCETYPE, GetType)() override; - STDMETHOD_(DWORD, SetLOD)(DWORD LODNew) override; - STDMETHOD_(DWORD, GetLOD)() override; - STDMETHOD_(DWORD, GetLevelCount)() override; - STDMETHOD(SetAutoGenFilterType)(D3DTEXTUREFILTERTYPE FilterType) override; - STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)() override; - STDMETHOD_(void, GenerateMipSubLevels)() override; - STDMETHOD(GetLevelDesc)(UINT Level, D3DSURFACE_DESC* pDesc) override; - STDMETHOD(GetSurfaceLevel)(UINT Level, IDirect3DSurface9** ppSurfaceLevel) override; - STDMETHOD(LockRect)(UINT Level, D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect, DWORD Flags) override; - STDMETHOD(UnlockRect)(UINT Level) override; - STDMETHOD(AddDirtyRect)(CONST RECT* pDirtyRect) override; - - [[nodiscard]] HashTuple GetHash() const; -}; diff --git a/header/uMod_IDirect3DVolumeTexture9.h b/header/uMod_IDirect3DVolumeTexture9.h deleted file mode 100644 index 3e6b4e6..0000000 --- a/header/uMod_IDirect3DVolumeTexture9.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include - -interface uMod_IDirect3DVolumeTexture9 : IDirect3DVolumeTexture9 { - uMod_IDirect3DVolumeTexture9(IDirect3DVolumeTexture9** ppTex, IDirect3DDevice9* pIDirect3DDevice9) - : m_D3Dtex(*ppTex), - m_D3Ddev(pIDirect3DDevice9) - {} - - virtual ~uMod_IDirect3DVolumeTexture9() = default; - - // callback interface - IDirect3DVolumeTexture9* m_D3Dtex = nullptr; - uMod_IDirect3DVolumeTexture9* CrossRef_D3Dtex = nullptr; - IDirect3DDevice9* m_D3Ddev = nullptr; - TextureFileStruct* Reference = nullptr; - HashTuple Hash = {}; - bool FAKE = false; - - // original interface - STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj) override; - STDMETHOD_(ULONG, AddRef)() override; - STDMETHOD_(ULONG, Release)() override; - STDMETHOD(GetDevice)(IDirect3DDevice9** ppDevice) override; - STDMETHOD(SetPrivateData)(REFGUID refguid,CONST void* pData, DWORD SizeOfData, DWORD Flags) override; - STDMETHOD(GetPrivateData)(REFGUID refguid, void* pData, DWORD* pSizeOfData) override; - STDMETHOD(FreePrivateData)(REFGUID refguid) override; - STDMETHOD_(DWORD, SetPriority)(DWORD PriorityNew) override; - STDMETHOD_(DWORD, GetPriority)() override; - STDMETHOD_(void, PreLoad)() override; - STDMETHOD_(D3DRESOURCETYPE, GetType)() override; - STDMETHOD_(DWORD, SetLOD)(DWORD LODNew) override; - STDMETHOD_(DWORD, GetLOD)() override; - STDMETHOD_(DWORD, GetLevelCount)() override; - STDMETHOD(SetAutoGenFilterType)(D3DTEXTUREFILTERTYPE FilterType) override; - STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)() override; - STDMETHOD_(void, GenerateMipSubLevels)() override; - STDMETHOD(AddDirtyBox)(CONST D3DBOX* pDirtyBox) override; - STDMETHOD(GetLevelDesc)(UINT Level, D3DVOLUME_DESC* pDesc) override; - STDMETHOD(GetVolumeLevel)(UINT Level, IDirect3DVolume9** ppVolumeLevel) override; - STDMETHOD(LockBox)(UINT Level, D3DLOCKED_BOX* pLockedVolume, CONST D3DBOX* pBox, DWORD Flags) override; - STDMETHOD(UnlockBox)(UINT Level) override; - - - [[nodiscard]] HashTuple GetHash() const; -}; diff --git a/modules/ModfileLoader.ixx b/modules/ModfileLoader.ixx index 02dbbd1..e38c3cc 100644 --- a/modules/ModfileLoader.ixx +++ b/modules/ModfileLoader.ixx @@ -13,7 +13,8 @@ import TextureFunction; namespace { bool use_64_bit_crc = false; - HashType GetCrcFromFilename(const std::string& filename) { + HashType GetCrcFromFilename(const std::string& filename) + { const static std::regex re(R"(0[xX][0-9a-fA-F]{4,16})", std::regex::optimize); std::smatch match; if (!std::regex_search(filename, match, re)) { @@ -39,7 +40,8 @@ namespace { } namespace HashCheck { - export bool Use64BitCrc() { + export bool Use64BitCrc() + { return use_64_bit_crc; } } @@ -52,8 +54,7 @@ export class ModfileLoader { 0x74, 0x61, 0x67, 0x5B, 0x60, 0x70, 0x45, 0x74, 0x5C, 0x22, 0x74, 0x5D, 0x6E, 0x6A, 0x73, 0x41, 0x77, 0x6E, 0x46, 0x47, 0x77, 0x49, 0x0C, 0x4B, - 0x46, 0x6F - }; + 0x46, 0x6F}; public: ModfileLoader(const std::filesystem::path& fileName); @@ -61,7 +62,6 @@ public: std::vector GetContents() const; private: - std::vector GetTpfContents() const; std::vector GetFileContents() const; diff --git a/modules/ModfileLoader_TpfReader.ixx b/modules/ModfileLoader_TpfReader.ixx index 81410d3..36e9f9f 100644 --- a/modules/ModfileLoader_TpfReader.ixx +++ b/modules/ModfileLoader_TpfReader.ixx @@ -35,7 +35,7 @@ public: // in the other zip libraries, these had to be cut off, with libzip we need to zero them out // cutting them off makes the archive invalid - //data.resize(last_zero); + // data.resize(last_zero); return data; } diff --git a/modules/TextureClient.ixx b/modules/TextureClient.ixx index 99449da..4b84471 100644 --- a/modules/TextureClient.ixx +++ b/modules/TextureClient.ixx @@ -2,10 +2,11 @@ module; #include "Main.h" #include "Error.h" -#include "uMod_IDirect3DTexture9.h" +#include "D3D9State.h" #include #include #include +#include export module TextureClient; import TextureFunction; @@ -14,27 +15,51 @@ import ModfileLoader; export std::vector> modlists_contents; struct PendingOp { - enum class Kind { Add, Remove }; + enum class Kind { + Add, + Remove + }; Kind kind; HashType hash; std::vector data; }; +// Couples a value with the mutex guarding it; the value is only reachable while +// the lock is held. +template +class Guarded { + std::mutex mutex; + T value; + +public: + template + auto with(Fn&& fn) + { + std::lock_guard lock(mutex); + return fn(value); + } +}; + /* - * An object of this class is owned by each d3d9 device. - * All other functions are called from the render thread instance of the game itself. + * Owned by each d3d9 device (see D3D9Hooks.cpp). Holds the side-state for every + * texture and performs the actual modding. The On*() methods are the vtable-hook + * entry points, all driven by the game's render thread. */ export class TextureClient { public: TextureClient(IDirect3DDevice9* device); ~TextureClient(); - int AddTexture(uModTexturePtr auto pTexture); - int RemoveTexture(uModTexturePtr auto pTexture); //called from uMod_IDirect3DTexture9::Release() - int LookUpToMod(uModTexturePtr auto pTexture); - // called at the end AddTexture(...) and from Device->UpdateTexture(...) + // Called from the hooked vtable slots: + TexState* OnCreateTexture(IDirect3DBaseTexture9* texture, TexType type); + void OnBeginScene(); + // The fake replacement when `texture` is a modded original, else `texture`. + IDirect3DBaseTexture9* ResolveBinding(IDirect3DBaseTexture9* texture); + // For GetTexture: the original behind one of our fakes, or nullptr. + IDirect3DBaseTexture9* ResolveOriginalFromFake(IDirect3DBaseTexture9* texture); + void OnUpdateTexture(IDirect3DBaseTexture9* source, IDirect3DBaseTexture9* destination); + void OnReleaseTexture(IDirect3DBaseTexture9* texture); // called once the real refcount hit zero - int MergeUpdate(); //called from uMod_IDirect3DDevice9::BeginScene() void Initialize(); void EnqueueAdd(HashType hash, std::vector data); @@ -44,55 +69,80 @@ public: static int RemoveFile(const std::filesystem::path& path); static std::vector GetFiles(); - std::vector OriginalTextures; - // stores the pointer to the uMod_IDirect3DTexture9 objects created by the game - std::vector OriginalVolumeTextures; - // stores the pointer to the uMod_IDirect3DVolumeTexture9 objects created by the game - std::vector OriginalCubeTextures; - // stores the pointer to the uMod_IDirect3DCubeTexture9 objects created by the game + // The texture Release hook has only a texture pointer, so it finds its client here. + static TextureClient* CurrentClient(); private: IDirect3DDevice9* D3D9Device; - // Cached info about whether this id a dx9ex device or not; used for proxy functions - bool isDirectXExDevice = false; - // DX9 proxy functions - void SetLastCreatedTexture(uMod_IDirect3DTexture9*); - void SetLastCreatedVolumeTexture(uMod_IDirect3DVolumeTexture9*); - void SetLastCreatedCubeTexture(uMod_IDirect3DCubeTexture9*); + // Side-state keyed by real texture pointer: the game's textures vs. our fakes. + std::recursive_mutex registry_mutex; + std::unordered_map originals; + std::unordered_map fakes; + // Hashed one creation later, once the game has filled it with data. + IDirect3DBaseTexture9* last_created[3] = {}; + + bool loading_fake = false; // set while LoadTexture() drives CreateTexture internally + bool shutting_down = false; // set in ~TextureClient so the Release hook stops touching us bool should_update = false; + int AddTexture(IDirect3DBaseTexture9* texture); // hash a freshly filled original + look up its mod + int LookUpToMod(TexState* state); // switch in a fake if a mod matches the hash + int LoadTexture(TextureFileStruct* file_in_memory, IDirect3DBaseTexture9** ppTexture, TexState** ppState); + + static void Switch(TexState* original, TexState* fake); + static void Unswitch(TexState* original); + void UnswitchAndRelease(TexState* original); // unswitch + release our fake + + int MergeUpdate(); + int LockMutex(); int UnlockMutex(); HANDLE hMutex; - std::mutex pending_mutex; - std::vector pending_ops; + Guarded> pending_ops; void ProcessPendingOps(); void RemoveModdedTexture(HashType hash); - std::unordered_map> modded_textures; - // array which stores the file in memory and the hash of each texture to be modded - - // called if a target texture is found - int LoadTexture(TextureFileStruct* file_in_memory, uModTexturePtrPtr auto ppTexture); + std::unordered_map> modded_textures; // hash -> mod file in memory static void LoadStartupModlists(); + // Enqueue an Add per distinct non-zero hash, free the structs, return the hashes + // in load order; accumulates moved bytes into loaded_bytes when given. + static std::vector IngestModfile(std::vector>& texture_file_structs, uint64_t* loaded_bytes = nullptr); + + // Kept in load order, which is priority order: on a hash collision the + // earlier file wins (see ProcessPendingOps). + struct LoadedFile { + std::filesystem::path path; + std::vector hashes; + }; + static inline std::mutex global_mutex; static inline TextureClient* current_client = nullptr; - static inline std::map> loaded_files; + // A vector, not a map: tens of mods at most, and their order is meaningful. + static inline std::vector loaded_files; + + // Caller holds global_mutex; path must already be absolute. + static std::vector::iterator FindLoadedFile(const std::filesystem::path& absolute_path) + { + return std::ranges::find(loaded_files, absolute_path, &LoadedFile::path); + } }; +TextureClient* TextureClient::CurrentClient() +{ + std::lock_guard lk(global_mutex); + return current_client; +} + TextureClient::TextureClient(IDirect3DDevice9* device) { Message("TextureClient::TextureClient(): %p\n", this); D3D9Device = device; - void* cpy; - isDirectXExDevice = D3D9Device->QueryInterface(IID_IDirect3DTexture9, &cpy) == 0x01000001L; - hMutex = CreateMutex(nullptr, false, nullptr); std::lock_guard lk(global_mutex); @@ -107,6 +157,23 @@ TextureClient::~TextureClient() std::lock_guard lk(global_mutex); if (current_client == this) current_client = nullptr; } + + { + std::lock_guard lk(registry_mutex); + shutting_down = true; // the texture Release hook now no-ops for our textures + + // Drop side-state but don't Release the textures: the game already released + // its originals (and our fakes with them), and the device may be gone. + for (const auto state : fakes | std::views::values) { + delete state; + } + fakes.clear(); + for (const auto state : originals | std::views::values) { + delete state; + } + originals.clear(); + } + if (hMutex != nullptr) { CloseHandle(hMutex); } @@ -116,13 +183,216 @@ TextureClient::~TextureClient() modded_textures.clear(); } +void TextureClient::Switch(TexState* original, TexState* fake) +{ + original->partner = fake; + fake->partner = original; +} + +void TextureClient::Unswitch(TexState* original) +{ + if (original->partner != nullptr) { + original->partner->partner = nullptr; + original->partner = nullptr; + } +} + +void TextureClient::UnswitchAndRelease(TexState* original) +{ + TexState* fake = original->partner; + if (fake == nullptr) return; + Unswitch(original); // detach before releasing so the fake's Release hook won't touch `original` + if (fake->real) fake->real->Release(); // re-enters OnReleaseTexture(fake), which frees its state +} + +TexState* TextureClient::OnCreateTexture(IDirect3DBaseTexture9* texture, TexType type) +{ + std::lock_guard lk(registry_mutex); + + const auto state = new TexState(); + state->real = texture; + state->device = D3D9Device; + state->type = type; + + if (loading_fake) { + // A replacement we're creating: track as a fake, skip the originals bookkeeping. + state->isFake = true; + fakes.emplace(texture, state); + return state; + } + + originals.emplace(texture, state); + + // The previous texture of this type is now filled, so hash it. + if (const auto last = last_created[static_cast(type)]) { + AddTexture(last); + } + last_created[static_cast(type)] = texture; + return state; +} + +int TextureClient::AddTexture(IDirect3DBaseTexture9* texture) +{ + const auto it = originals.find(texture); + if (it == originals.end()) return RETURN_OK; + const auto state = it->second; + + // No longer pending. + if (last_created[static_cast(state->type)] == texture) { + last_created[static_cast(state->type)] = nullptr; + } + + if (gl_ErrorState & uMod_ERROR_FATAL) { + return RETURN_FATAL_ERROR; + } + + state->hash = GetTextureHash(state); + if (!state->hash) { + return RETURN_FATAL_ERROR; + } + + return LookUpToMod(state); // check if this texture should be modded +} + +int TextureClient::LookUpToMod(TexState* state) +{ + Message("TextureClient::LookUpToMod( %p): hash: %#lX\n", state->real, state->hash); + if (state->partner != nullptr) + return RETURN_OK; // already switched + + auto found = modded_textures.find(state->hash.crc32); + if (found == modded_textures.end()) + if (found = modded_textures.find(state->hash.crc64), !state->hash.crc64 || found == modded_textures.end()) + return RETURN_OK; + + const auto textureFileStruct = found->second; + + IDirect3DBaseTexture9* fake_texture = nullptr; + TexState* fake_state = nullptr; + if (const int ret = LoadTexture(textureFileStruct, &fake_texture, &fake_state); ret != RETURN_OK) + return ret; + + Switch(state, fake_state); + fake_state->reference = textureFileStruct; + return RETURN_OK; +} + +int TextureClient::LoadTexture(TextureFileStruct* file_in_memory, IDirect3DBaseTexture9** ppTexture, TexState** ppState) +{ + Message("LoadTexture( %p, %#lX): %p\n", file_in_memory, file_in_memory->crc_hash, this); + *ppTexture = nullptr; + *ppState = nullptr; + + // CreateDDSTextureFromMemoryEx calls the hooked CreateTexture; loading_fake + // makes that hook register the result as a fake, not a game original. + IDirect3DTexture9* texture = nullptr; + loading_fake = true; + const auto ret = DirectX::CreateDDSTextureFromMemoryEx( + D3D9Device, + file_in_memory->data.data(), + file_in_memory->data.size(), + 0, D3DPOOL_MANAGED, false, + &texture); + loading_fake = false; + + if (ret != D3D_OK || texture == nullptr) { + Warning("LoadDDSTexture (%p, %#lX): FAILED ret: \n", file_in_memory->data.data(), file_in_memory->crc_hash, ret); + return RETURN_TEXTURE_NOT_LOADED; + } + + const auto fake = static_cast(texture); + const auto state_it = fakes.find(fake); + ASSERT(state_it != fakes.end()); // must have been registered by the CreateTexture hook + *ppTexture = fake; + *ppState = state_it->second; + + Message("LoadTexture (%p, %#lX): DONE\n", fake, file_in_memory->crc_hash); + return RETURN_OK; +} + +IDirect3DBaseTexture9* TextureClient::ResolveBinding(IDirect3DBaseTexture9* texture) +{ + if (texture == nullptr) return nullptr; + std::lock_guard lk(registry_mutex); + const auto it = originals.find(texture); + if (it != originals.end() && it->second->partner != nullptr) { + return it->second->partner->real; // bind the fake in place of the original + } + return texture; +} + +IDirect3DBaseTexture9* TextureClient::ResolveOriginalFromFake(IDirect3DBaseTexture9* texture) +{ + if (texture == nullptr) return nullptr; + std::lock_guard lk(registry_mutex); + const auto it = fakes.find(texture); + if (it != fakes.end() && it->second->partner != nullptr) { + return it->second->partner->real; + } + return nullptr; +} + +void TextureClient::OnBeginScene() +{ + { + std::lock_guard lk(registry_mutex); + for (int type = 0; type < 3; ++type) { + if (last_created[type] != nullptr) { + AddTexture(last_created[type]); // hashes + clears the slot + } + } + } + MergeUpdate(); +} + +void TextureClient::OnUpdateTexture(IDirect3DBaseTexture9* source, IDirect3DBaseTexture9* destination) +{ + // The copy already happened; re-hash both textures and re-run the mod lookup. + std::lock_guard lk(registry_mutex); + + auto refresh = [this](IDirect3DBaseTexture9* texture) { + const auto it = originals.find(texture); + if (it == originals.end()) return; + const auto state = it->second; + const auto hash = GetTextureHash(state); + if (hash == state->hash) return; // unchanged + state->hash = hash; + if (state->partner != nullptr) UnswitchAndRelease(state); + if (hash) LookUpToMod(state); + }; + refresh(source); + refresh(destination); +} + +void TextureClient::OnReleaseTexture(IDirect3DBaseTexture9* texture) +{ + std::lock_guard lk(registry_mutex); + if (shutting_down) return; // ~TextureClient is tearing everything down itself + + // A fake of ours being released (either by us during cleanup, or transitively). + if (const auto fit = fakes.find(texture); fit != fakes.end()) { + const auto state = fit->second; + if (state->partner != nullptr) state->partner->partner = nullptr; + fakes.erase(fit); + delete state; + return; + } + + // A game texture (original) reaching zero references. + if (const auto oit = originals.find(texture); oit != originals.end()) { + const auto state = oit->second; + if (last_created[static_cast(state->type)] == texture) { + last_created[static_cast(state->type)] = nullptr; + } + originals.erase(oit); + UnswitchAndRelease(state); // release the fake we held for it, if any + delete state; + } +} + int TextureClient::MergeUpdate() { - bool has_pending; - { - std::lock_guard lk(pending_mutex); - has_pending = !pending_ops.empty(); - } + const bool has_pending = pending_ops.with([](auto& ops) { return !ops.empty(); }); if (!should_update && !has_pending) return RETURN_OK; if (const int ret = LockMutex()) { gl_ErrorState |= uMod_ERROR_TEXTURE; @@ -133,19 +403,12 @@ int TextureClient::MergeUpdate() ProcessPendingOps(); - for (const auto pTexture : OriginalTextures) { - if (pTexture->CrossRef_D3Dtex == nullptr) { - LookUpToMod(pTexture); - } - } - for (const auto pTexture : OriginalVolumeTextures) { - if (pTexture->CrossRef_D3Dtex == nullptr) { - LookUpToMod(pTexture); - } - } - for (const auto pTexture : OriginalCubeTextures) { - if (pTexture->CrossRef_D3Dtex == nullptr) { - LookUpToMod(pTexture); + { + std::lock_guard lk(registry_mutex); + for (const auto state : originals | std::views::values) { + if (state->partner == nullptr && state->hash) { + LookUpToMod(state); + } } } @@ -156,24 +419,19 @@ int TextureClient::MergeUpdate() void TextureClient::EnqueueAdd(HashType hash, std::vector data) { if (!hash) return; - std::lock_guard lk(pending_mutex); - pending_ops.push_back(PendingOp{PendingOp::Kind::Add, hash, std::move(data)}); + pending_ops.with([&](auto& ops) { ops.push_back(PendingOp{PendingOp::Kind::Add, hash, std::move(data)}); }); } void TextureClient::EnqueueRemove(HashType hash) { if (!hash) return; - std::lock_guard lk(pending_mutex); - pending_ops.push_back(PendingOp{PendingOp::Kind::Remove, hash, {}}); + pending_ops.with([&](auto& ops) { ops.push_back(PendingOp{PendingOp::Kind::Remove, hash, {}}); }); } void TextureClient::ProcessPendingOps() { std::vector ops; - { - std::lock_guard lk(pending_mutex); - ops.swap(pending_ops); - } + pending_ops.with([&](auto& pending) { ops.swap(pending); }); for (auto& op : ops) { if (op.kind == PendingOp::Kind::Add) { if (modded_textures.contains(op.hash)) continue; @@ -195,51 +453,27 @@ void TextureClient::RemoveModdedTexture(HashType hash) if (it == modded_textures.end()) return; const auto texture_file_struct = it->second; - auto unswitch_in = [texture_file_struct](auto& vec) { - for (auto* original_texture : vec) { - auto* fake_texture = original_texture->CrossRef_D3Dtex; - if (fake_texture && fake_texture->Reference == texture_file_struct) { - UnswitchTextures(original_texture); - fake_texture->Release(); + { + std::lock_guard lk(registry_mutex); + for (const auto original : originals | std::views::values) { + const auto fake = original->partner; + if (fake != nullptr && fake->reference == texture_file_struct) { + UnswitchAndRelease(original); } } - }; - unswitch_in(OriginalTextures); - unswitch_in(OriginalVolumeTextures); - unswitch_in(OriginalCubeTextures); + } modded_textures.erase(it); delete texture_file_struct; } -void TextureClient::SetLastCreatedTexture(uMod_IDirect3DTexture9* texture) -{ - if (isDirectXExDevice) - return static_cast(D3D9Device)->SetLastCreatedTexture(texture); - return static_cast(D3D9Device)->SetLastCreatedTexture(texture); -} - -void TextureClient::SetLastCreatedVolumeTexture(uMod_IDirect3DVolumeTexture9* texture) -{ - if (isDirectXExDevice) - return static_cast(D3D9Device)->SetLastCreatedVolumeTexture(texture); - return static_cast(D3D9Device)->SetLastCreatedVolumeTexture(texture); -} - -void TextureClient::SetLastCreatedCubeTexture(uMod_IDirect3DCubeTexture9* texture) -{ - if (isDirectXExDevice) - return static_cast(D3D9Device)->SetLastCreatedCubeTexture(texture); - return static_cast(D3D9Device)->SetLastCreatedCubeTexture(texture); -} - int TextureClient::LockMutex() { if ((gl_ErrorState & (uMod_ERROR_FATAL | uMod_ERROR_MUTEX))) { return RETURN_NO_MUTEX; } if (WAIT_OBJECT_0 != WaitForSingleObject(hMutex, 100)) { - return RETURN_MUTEX_LOCK; //waiting 100ms, to wait infinite pass INFINITE + return RETURN_MUTEX_LOCK; // waiting 100ms, to wait infinite pass INFINITE } return RETURN_OK; } @@ -289,13 +523,31 @@ std::vector> ProcessModfile(const std::filesystem return texture_file_structs; } +std::vector TextureClient::IngestModfile(std::vector>& texture_file_structs, uint64_t* loaded_bytes) +{ + std::vector hashes; + for (auto* texture_file_struct : texture_file_structs) { + const auto hash = texture_file_struct->crc_hash; + if (hash && std::ranges::find(hashes, hash) == hashes.end()) { + hashes.push_back(hash); + if (loaded_bytes) *loaded_bytes += texture_file_struct->data.size(); + if (current_client) { + current_client->EnqueueAdd(hash, std::move(texture_file_struct->data)); + } + } + delete texture_file_struct; + } + texture_file_structs.clear(); + return hashes; +} + std::vector TextureClient::GetFiles() { std::lock_guard lk(global_mutex); std::vector result; result.reserve(loaded_files.size()); - for (const auto& key : loaded_files | std::views::keys) { - result.push_back(key); + for (const auto& loaded_file : loaded_files) { + result.push_back(loaded_file.path); } return result; } @@ -304,10 +556,10 @@ int TextureClient::RemoveFile(const std::filesystem::path& path) { const auto absolute_path = std::filesystem::absolute(path); std::lock_guard lk(global_mutex); - const auto it = loaded_files.find(absolute_path); + const auto it = FindLoadedFile(absolute_path); if (it == loaded_files.end()) return RETURN_FILE_NOT_LOADED; if (current_client) { - for (const auto hash : it->second) { + for (const auto hash : it->hashes) { current_client->EnqueueRemove(hash); } } @@ -320,35 +572,25 @@ int TextureClient::AddFile(const std::filesystem::path& path) const auto absolute_path = std::filesystem::absolute(path); { std::lock_guard lk(global_mutex); - if (loaded_files.contains(absolute_path)) return RETURN_EXISTS; + if (FindLoadedFile(absolute_path) != loaded_files.end()) return RETURN_EXISTS; } if (!std::filesystem::exists(absolute_path)) return RETURN_FILE_NOT_LOADED; const auto file_size = std::filesystem::file_size(absolute_path); - const auto texture_file_structs = ProcessModfile(absolute_path, file_size > 400'000'000); + auto texture_file_structs = ProcessModfile(absolute_path, file_size > 400'000'000); if (texture_file_structs.empty()) return RETURN_FILE_NOT_LOADED; std::lock_guard lk(global_mutex); // Re-check under lock; another thread may have loaded the same path concurrently. - if (loaded_files.contains(absolute_path)) { - for (auto* texture_file_struct : texture_file_structs) delete texture_file_struct; + if (FindLoadedFile(absolute_path) != loaded_files.end()) { + for (auto* texture_file_struct : texture_file_structs) + delete texture_file_struct; return RETURN_EXISTS; } - std::vector hashes; - for (auto* texture_file_struct : texture_file_structs) { - const auto hash = texture_file_struct->crc_hash; - if (hash && std::ranges::find(hashes, hash) == hashes.end()) { - hashes.push_back(hash); - if (current_client) { - current_client->EnqueueAdd(hash, std::move(texture_file_struct->data)); - } - } - delete texture_file_struct; - } - + auto hashes = IngestModfile(texture_file_structs); if (hashes.empty()) return RETURN_TEXTURE_NOT_LOADED; - loaded_files.emplace(absolute_path, std::move(hashes)); + loaded_files.push_back({absolute_path, std::move(hashes)}); return RETURN_OK; } @@ -391,26 +633,15 @@ void TextureClient::LoadStartupModlists() auto texture_file_structs = futures[i].get(); std::lock_guard lk(global_mutex); - if (loaded_files.contains(modfiles[i])) { - for (const auto* texture_file_struct : texture_file_structs) delete texture_file_struct; + if (FindLoadedFile(modfiles[i]) != loaded_files.end()) { + for (const auto* texture_file_struct : texture_file_structs) + delete texture_file_struct; continue; } - std::vector hashes; - for (auto* texture_file_struct : texture_file_structs) { - const auto hash = texture_file_struct->crc_hash; - if (hash && std::ranges::find(hashes, hash) == hashes.end()) { - hashes.push_back(hash); - loaded_size += texture_file_struct->data.size(); - if (current_client) { - current_client->EnqueueAdd(hash, std::move(texture_file_struct->data)); - } - } - delete texture_file_struct; - } - + auto hashes = IngestModfile(texture_file_structs, &loaded_size); if (!hashes.empty()) { - loaded_files.emplace(modfiles[i], std::move(hashes)); + loaded_files.push_back({modfiles[i], std::move(hashes)}); } } Info("LoadStartupModlists: %llu bytes (%llu MB)\n", loaded_size, loaded_size / 1024 / 1024); @@ -421,26 +652,13 @@ void TextureClient::Initialize() const auto t1 = std::chrono::high_resolution_clock::now(); Info("Initialize: begin\n"); - // now load files that were added by AddFile() before the device existed - std::vector pre_existing_paths; - { - std::lock_guard lk(global_mutex); - pre_existing_paths.reserve(loaded_files.size()); - for (const auto& key : loaded_files | std::views::keys) pre_existing_paths.push_back(key); - } - for (const auto& path : pre_existing_paths) { + // AddFile() before the device existed recorded files but couldn't enqueue them + // (no client yet); enqueue them now. + for (const auto& path : GetFiles()) { if (!std::filesystem::exists(path)) continue; const auto file_size = std::filesystem::file_size(path); auto texture_file_structs = ProcessModfile(path, file_size > 400'000'000); - std::vector seen; - for (auto* texture_file_struct : texture_file_structs) { - const auto hash = texture_file_struct->crc_hash; - if (hash && std::ranges::find(seen, hash) == seen.end()) { - seen.push_back(hash); - EnqueueAdd(hash, std::move(texture_file_struct->data)); - } - delete texture_file_struct; - } + IngestModfile(texture_file_structs); } LoadStartupModlists(); @@ -449,125 +667,3 @@ void TextureClient::Initialize() const auto ms = duration_cast(t2 - t1); Info("Initialize: end, took %d ms\n", ms); } - -int TextureClient::AddTexture(uModTexturePtr auto pTexture) -{ - if constexpr (std::same_as) { - SetLastCreatedTexture(nullptr); - } - else if constexpr (std::same_as) { - SetLastCreatedVolumeTexture(nullptr); - } - else if constexpr (std::same_as) { - SetLastCreatedCubeTexture(nullptr); - } - - if (pTexture->FAKE) { - return RETURN_OK; // this is a fake texture - } - - if (gl_ErrorState & uMod_ERROR_FATAL) { - return RETURN_FATAL_ERROR; - } - - Message("TextureClient::AddTexture( Cube: %p): %p (thread: %u)\n", pTexture, this, GetCurrentThreadId()); - - pTexture->Hash = pTexture->GetHash(); - if (!pTexture->Hash) { - return RETURN_FATAL_ERROR; - } - - if constexpr (std::same_as) { - OriginalTextures.push_back(pTexture); - } - else if constexpr (std::same_as) { - OriginalVolumeTextures.push_back(pTexture); - } - else if constexpr (std::same_as) { - OriginalCubeTextures.push_back(pTexture); - } - - return LookUpToMod(pTexture); // check if this texture should be modded -} - -int TextureClient::RemoveTexture(uModTexturePtr auto pTexture) -{ - Message("TextureClient::RemoveTexture( %p, %#lX): %p\n", pTexture, pTexture->Hash, this); - - if (gl_ErrorState & uMod_ERROR_FATAL) { - return RETURN_FATAL_ERROR; - } - - if (!pTexture->FAKE) { - if constexpr (std::same_as) { - utils::erase_first(OriginalTextures, pTexture); - } - else if constexpr (std::same_as) { - utils::erase_first(OriginalVolumeTextures, pTexture); - } - else if constexpr (std::same_as) { - utils::erase_first(OriginalCubeTextures, pTexture); - } - } - if (!pTexture->Reference) - return RETURN_OK; // Should this ever happen? - return RETURN_OK; -} - -int TextureClient::LookUpToMod(uModTexturePtr auto pTexture) -{ - Message("TextureClient::LookUpToMod( %p): hash: %#lX\n", pTexture, pTexture->Hash); - int ret = RETURN_OK; - - if (pTexture->CrossRef_D3Dtex != nullptr) - return ret; // bug, this texture is already switched - - auto found = modded_textures.find(pTexture->Hash.crc32); - if (found == modded_textures.end()) - if (found = modded_textures.find(pTexture->Hash.crc64), !pTexture->Hash.crc64 || found == modded_textures.end()) - return ret; - - const auto textureFileStruct = found->second; - - decltype(pTexture) fake_texture; - ret = LoadTexture(textureFileStruct, &fake_texture); - if (ret != RETURN_OK) - return ret; - - ret = SwitchTextures(fake_texture, pTexture); - if (ret != RETURN_OK) { - Message("TextureClient::LookUpToMod(): textures not switched %#lX\n", textureFileStruct->crc_hash); - fake_texture->Release(); - return ret; - } - fake_texture->Reference = textureFileStruct; - return ret; -} - -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 (const auto ret = DirectX::CreateDDSTextureFromMemoryEx( - D3D9Device, - file_in_memory->data.data(), - file_in_memory->data.size(), - 0, D3DPOOL_MANAGED, false, - reinterpret_cast(ppTexture)); ret != D3D_OK) { - *ppTexture = nullptr; - Warning("LoadDDSTexture (%p, %#lX): FAILED ret: \n", file_in_memory->data.data(), file_in_memory->crc_hash, ret); - return RETURN_TEXTURE_NOT_LOADED; - } - if constexpr (std::same_as) { - SetLastCreatedTexture(nullptr); - } - else if constexpr (std::same_as) { - SetLastCreatedVolumeTexture(nullptr); - } - else if constexpr (std::same_as) { - SetLastCreatedCubeTexture(nullptr); - } - (*ppTexture)->FAKE = true; - - Message("LoadTexture (%p, %#lX): DONE\n", *ppTexture, file_in_memory->crc_hash); - return RETURN_OK; -} diff --git a/modules/TextureFunction.ixx b/modules/TextureFunction.ixx index 7b09302..a2ba01f 100644 --- a/modules/TextureFunction.ixx +++ b/modules/TextureFunction.ixx @@ -6,45 +6,7 @@ module; export module TextureFunction; -export template -concept uModTexturePtr = requires(T a) -{ - std::same_as || - std::same_as || - std::same_as; -}; - -export template -concept uModTexturePtrPtr = uModTexturePtr>; - -export template requires uModTexturePtr -void UnswitchTextures(T pTexture) -{ - decltype(pTexture) CrossRef = pTexture->CrossRef_D3Dtex; - if (CrossRef != nullptr) { - std::swap(pTexture->m_D3Dtex, CrossRef->m_D3Dtex); - - // cancel the link - CrossRef->CrossRef_D3Dtex = nullptr; - pTexture->CrossRef_D3Dtex = nullptr; - } -} - -export 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 - pTexture1->CrossRef_D3Dtex = pTexture2; - pTexture2->CrossRef_D3Dtex = pTexture1; - - // switch textures - std::swap(pTexture1->m_D3Dtex, pTexture2->m_D3Dtex); - return RETURN_OK; - } - return RETURN_TEXTURE_NOT_SWITCHED; -} - +// clang-format off constexpr auto crctab64 = std::to_array({ 0x0000000000000000ULL, 0x7ad870c830358979ULL, 0xf5b0e190606b12f2ULL, 0x8f689158505e9b8bULL, 0xc038e5739841b68fULL, 0xbae095bba8743ff6ULL, @@ -133,10 +95,12 @@ constexpr auto crctab64 = std::to_array({ 0xa6df411fbfb21ca3ULL, 0xdc0731d78f8795daULL, 0x536fa08fdfd90e51ULL, 0x29b7d047efec8728ULL }); +// clang-format on export namespace TextureFunction { - uint64_t get_crc64(const char* data, unsigned int length) { + uint64_t get_crc64(const char* data, unsigned int length) + { uint64_t crc = 0xFFFFFFFFFFFFFFFFULL; while (length--) { @@ -162,7 +126,7 @@ export namespace TextureFunction { int GetBitsFromFormat(D3DFORMAT format) { - switch (format) //switch trough the formats to calculate the size of the raw data + switch (format) // switch trough the formats to calculate the size of the raw data { case D3DFMT_A1: // 1-bit monochrome. { @@ -170,75 +134,75 @@ export namespace TextureFunction { } case D3DFMT_R3G3B2: // 8-bit RGB texture format using 3 bits for red, 3 bits for green, and 2 bits for blue. - case D3DFMT_A8: // 8-bit alpha only. - case D3DFMT_A8P8: // 8-bit color indexed with 8 bits of alpha. - case D3DFMT_P8: // 8-bit color indexed. - case D3DFMT_L8: // 8-bit luminance only. - case D3DFMT_A4L4: // 8-bit using 4 bits each for alpha and luminance. + case D3DFMT_A8: // 8-bit alpha only. + case D3DFMT_A8P8: // 8-bit color indexed with 8 bits of alpha. + case D3DFMT_P8: // 8-bit color indexed. + case D3DFMT_L8: // 8-bit luminance only. + case D3DFMT_A4L4: // 8-bit using 4 bits each for alpha and luminance. case D3DFMT_FORCE_DWORD: case D3DFMT_S8_LOCKABLE: // A lockable 8-bit stencil buffer. { return 8; } - case D3DFMT_D16_LOCKABLE: //16-bit z-buffer bit depth. - case D3DFMT_D15S1: // 16-bit z-buffer bit depth where 15 bits are reserved for the depth channel and 1 bit is reserved for the stencil channel. - case D3DFMT_L6V5U5: // 16-bit bump-map format with luminance using 6 bits for luminance, and 5 bits each for v and u. - case D3DFMT_V8U8: // 16-bit bump-map format using 8 bits each for u and v data. - case D3DFMT_CxV8U8: // 16-bit normal compression format. The texture sampler computes the C channel from: C = sqrt(1 - U2 - V2). - case D3DFMT_R5G6B5: // 16-bit RGB pixel format with 5 bits for red, 6 bits for green, and 5 bits for blue. - case D3DFMT_X1R5G5B5: // 16-bit pixel format where 5 bits are reserved for each color. - case D3DFMT_A1R5G5B5: // 16-bit pixel format where 5 bits are reserved for each color and 1 bit is reserved for alpha. - case D3DFMT_A4R4G4B4: // 16-bit ARGB pixel format with 4 bits for each channel. - case D3DFMT_A8R3G3B2: // 16-bit ARGB texture format using 8 bits for alpha, 3 bits each for red and green, and 2 bits for blue. - case D3DFMT_X4R4G4B4: // 16-bit RGB pixel format using 4 bits for each color. - case D3DFMT_L16: // 16-bit luminance only. - case D3DFMT_R16F: // 16-bit float format using 16 bits for the red channel. - case D3DFMT_A8L8: // 16-bit using 8 bits each for alpha and luminance. - case D3DFMT_D16: // 16-bit z-buffer bit depth. - case D3DFMT_INDEX16: // 16-bit index buffer bit depth. - case D3DFMT_G8R8_G8B8: // ?? - case D3DFMT_R8G8_B8G8: // ?? - case D3DFMT_UYVY: // ?? - case D3DFMT_YUY2: // ?? + case D3DFMT_D16_LOCKABLE: // 16-bit z-buffer bit depth. + case D3DFMT_D15S1: // 16-bit z-buffer bit depth where 15 bits are reserved for the depth channel and 1 bit is reserved for the stencil channel. + case D3DFMT_L6V5U5: // 16-bit bump-map format with luminance using 6 bits for luminance, and 5 bits each for v and u. + case D3DFMT_V8U8: // 16-bit bump-map format using 8 bits each for u and v data. + case D3DFMT_CxV8U8: // 16-bit normal compression format. The texture sampler computes the C channel from: C = sqrt(1 - U2 - V2). + case D3DFMT_R5G6B5: // 16-bit RGB pixel format with 5 bits for red, 6 bits for green, and 5 bits for blue. + case D3DFMT_X1R5G5B5: // 16-bit pixel format where 5 bits are reserved for each color. + case D3DFMT_A1R5G5B5: // 16-bit pixel format where 5 bits are reserved for each color and 1 bit is reserved for alpha. + case D3DFMT_A4R4G4B4: // 16-bit ARGB pixel format with 4 bits for each channel. + case D3DFMT_A8R3G3B2: // 16-bit ARGB texture format using 8 bits for alpha, 3 bits each for red and green, and 2 bits for blue. + case D3DFMT_X4R4G4B4: // 16-bit RGB pixel format using 4 bits for each color. + case D3DFMT_L16: // 16-bit luminance only. + case D3DFMT_R16F: // 16-bit float format using 16 bits for the red channel. + case D3DFMT_A8L8: // 16-bit using 8 bits each for alpha and luminance. + case D3DFMT_D16: // 16-bit z-buffer bit depth. + case D3DFMT_INDEX16: // 16-bit index buffer bit depth. + case D3DFMT_G8R8_G8B8: // ?? + case D3DFMT_R8G8_B8G8: // ?? + case D3DFMT_UYVY: // ?? + case D3DFMT_YUY2: // ?? { return 16; } - case D3DFMT_R8G8B8: //24-bit RGB pixel format with 8 bits per channel. + case D3DFMT_R8G8B8: // 24-bit RGB pixel format with 8 bits per channel. { return 24; } - case D3DFMT_R32F: // 32-bit float format using 32 bits for the red channel. - case D3DFMT_X8L8V8U8: // 32-bit bump-map format with luminance using 8 bits for each channel. - case D3DFMT_A2W10V10U10: // 32-bit bump-map format using 2 bits for alpha and 10 bits each for w, v, and u. - case D3DFMT_Q8W8V8U8: // 32-bit bump-map format using 8 bits for each channel. - case D3DFMT_V16U16: // 32-bit bump-map format using 16 bits for each channel. - case D3DFMT_A8R8G8B8: // 32-bit ARGB pixel format with alpha, using 8 bits per channel. - case D3DFMT_X8R8G8B8: // 32-bit RGB pixel format, where 8 bits are reserved for each color. - case D3DFMT_A2B10G10R10: // 32-bit pixel format using 10 bits for each color and 2 bits for alpha. - case D3DFMT_A8B8G8R8: // 32-bit ARGB pixel format with alpha, using 8 bits per channel. - case D3DFMT_X8B8G8R8: // 32-bit RGB pixel format, where 8 bits are reserved for each color. - case D3DFMT_G16R16: // 32-bit pixel format using 16 bits each for green and red. - case D3DFMT_G16R16F: // 32-bit float format using 16 bits for the red channel and 16 bits for the green channel. - case D3DFMT_A2R10G10B10: // 32-bit pixel format using 10 bits each for red, green, and blue, and 2 bits for alpha. - case D3DFMT_D32: // 32-bit z-buffer bit depth. - case D3DFMT_D24S8: // 32-bit z-buffer bit depth using 24 bits for the depth channel and 8 bits for the stencil channel. - case D3DFMT_D24X8: //32-bit z-buffer bit depth using 24 bits for the depth channel. - case D3DFMT_D24X4S4: // 32-bit z-buffer bit depth using 24 bits for the depth channel and 4 bits for the stencil channel. + case D3DFMT_R32F: // 32-bit float format using 32 bits for the red channel. + case D3DFMT_X8L8V8U8: // 32-bit bump-map format with luminance using 8 bits for each channel. + case D3DFMT_A2W10V10U10: // 32-bit bump-map format using 2 bits for alpha and 10 bits each for w, v, and u. + case D3DFMT_Q8W8V8U8: // 32-bit bump-map format using 8 bits for each channel. + case D3DFMT_V16U16: // 32-bit bump-map format using 16 bits for each channel. + case D3DFMT_A8R8G8B8: // 32-bit ARGB pixel format with alpha, using 8 bits per channel. + case D3DFMT_X8R8G8B8: // 32-bit RGB pixel format, where 8 bits are reserved for each color. + case D3DFMT_A2B10G10R10: // 32-bit pixel format using 10 bits for each color and 2 bits for alpha. + case D3DFMT_A8B8G8R8: // 32-bit ARGB pixel format with alpha, using 8 bits per channel. + case D3DFMT_X8B8G8R8: // 32-bit RGB pixel format, where 8 bits are reserved for each color. + case D3DFMT_G16R16: // 32-bit pixel format using 16 bits each for green and red. + case D3DFMT_G16R16F: // 32-bit float format using 16 bits for the red channel and 16 bits for the green channel. + case D3DFMT_A2R10G10B10: // 32-bit pixel format using 10 bits each for red, green, and blue, and 2 bits for alpha. + case D3DFMT_D32: // 32-bit z-buffer bit depth. + case D3DFMT_D24S8: // 32-bit z-buffer bit depth using 24 bits for the depth channel and 8 bits for the stencil channel. + case D3DFMT_D24X8: // 32-bit z-buffer bit depth using 24 bits for the depth channel. + case D3DFMT_D24X4S4: // 32-bit z-buffer bit depth using 24 bits for the depth channel and 4 bits for the stencil channel. case D3DFMT_D32F_LOCKABLE: // A lockable format where the depth value is represented as a standard IEEE floating-point number. - case D3DFMT_D24FS8: // A non-lockable format that contains 24 bits of depth (in a 24-bit floating point format - 20e4) and 8 bits of stencil. - case D3DFMT_D32_LOCKABLE: // A lockable 32-bit depth buffer. - case D3DFMT_INDEX32: // 32-bit index buffer bit depth. + case D3DFMT_D24FS8: // A non-lockable format that contains 24 bits of depth (in a 24-bit floating point format - 20e4) and 8 bits of stencil. + case D3DFMT_D32_LOCKABLE: // A lockable 32-bit depth buffer. + case D3DFMT_INDEX32: // 32-bit index buffer bit depth. { return 32; } - case D3DFMT_G32R32F: // 64-bit float format using 32 bits for the red channel and 32 bits for the green channel. - case D3DFMT_Q16W16V16U16: // 64-bit bump-map format using 16 bits for each component. - case D3DFMT_A16B16G16R16: // 64-bit pixel format using 16 bits for each component. + case D3DFMT_G32R32F: // 64-bit float format using 32 bits for the red channel and 32 bits for the green channel. + case D3DFMT_Q16W16V16U16: // 64-bit bump-map format using 16 bits for each component. + case D3DFMT_A16B16G16R16: // 64-bit pixel format using 16 bits for each component. case D3DFMT_A16B16G16R16F: // 64-bit float format using 16 bits for the each channel (alpha, blue, green, red). { return 64; @@ -257,7 +221,7 @@ export namespace TextureFunction { case D3DFMT_DXT1: { return 4; } - default: //compressed formats + default: // compressed formats { return 4; } @@ -406,9 +370,9 @@ export namespace TextureFunction { return {}; } - #ifdef _DEBUG +#ifdef _DEBUG ImageSave(compressed_image, entry); - #endif +#endif return dds_blob; } } diff --git a/source/D3D9Hooks.cpp b/source/D3D9Hooks.cpp new file mode 100644 index 0000000..3606a57 --- /dev/null +++ b/source/D3D9Hooks.cpp @@ -0,0 +1,560 @@ +#include "Main.h" +#include "D3D9Hooks.h" +#include "MinHook.h" + +#include +#include +#include + +import TextureClient; +import TextureFunction; +import ModfileLoader; // HashCheck::Use64BitCrc + +// Hooked vtable slot indices (frozen D3D9 ABI). Device9Ex shares Device9's prefix. + +namespace { + + // --- IDirect3D9 / IDirect3D9Ex -------------------------------------- + constexpr int kIDirect3D9_CreateDevice = 16; + constexpr int kIDirect3D9Ex_CreateDeviceEx = 20; + + // --- IDirect3DDevice9 ----------------------------------------------- + constexpr int kDevice_Release = 2; + constexpr int kDevice_CreateTexture = 23; + constexpr int kDevice_CreateVolumeTexture = 24; + constexpr int kDevice_CreateCubeTexture = 25; + constexpr int kDevice_UpdateTexture = 31; + constexpr int kDevice_BeginScene = 41; + constexpr int kDevice_GetTexture = 64; + constexpr int kDevice_SetTexture = 65; + + // --- IDirect3D*Texture9 (IUnknown layout) --------------------------- + constexpr int kResource_Release = 2; + + void** GetVTable(void* com_object) + { + return *static_cast(com_object); + } + + // ---- trampolines to the real implementations ----------------------- + using CreateDevice_t = HRESULT(STDMETHODCALLTYPE*)(IDirect3D9*, UINT, D3DDEVTYPE, HWND, DWORD, D3DPRESENT_PARAMETERS*, IDirect3DDevice9**); + using CreateDeviceEx_t = HRESULT(STDMETHODCALLTYPE*)(IDirect3D9Ex*, UINT, D3DDEVTYPE, HWND, DWORD, D3DPRESENT_PARAMETERS*, D3DDISPLAYMODEEX*, IDirect3DDevice9Ex**); + using DeviceRelease_t = ULONG(STDMETHODCALLTYPE*)(IDirect3DDevice9*); + using CreateTexture_t = HRESULT(STDMETHODCALLTYPE*)(IDirect3DDevice9*, UINT, UINT, UINT, DWORD, D3DFORMAT, D3DPOOL, IDirect3DTexture9**, HANDLE*); + using CreateVolumeTexture_t = HRESULT(STDMETHODCALLTYPE*)(IDirect3DDevice9*, UINT, UINT, UINT, UINT, DWORD, D3DFORMAT, D3DPOOL, IDirect3DVolumeTexture9**, HANDLE*); + using CreateCubeTexture_t = HRESULT(STDMETHODCALLTYPE*)(IDirect3DDevice9*, UINT, UINT, DWORD, D3DFORMAT, D3DPOOL, IDirect3DCubeTexture9**, HANDLE*); + using UpdateTexture_t = HRESULT(STDMETHODCALLTYPE*)(IDirect3DDevice9*, IDirect3DBaseTexture9*, IDirect3DBaseTexture9*); + using BeginScene_t = HRESULT(STDMETHODCALLTYPE*)(IDirect3DDevice9*); + using SetTexture_t = HRESULT(STDMETHODCALLTYPE*)(IDirect3DDevice9*, DWORD, IDirect3DBaseTexture9*); + using GetTexture_t = HRESULT(STDMETHODCALLTYPE*)(IDirect3DDevice9*, DWORD, IDirect3DBaseTexture9**); + using ResourceRelease_t = ULONG(STDMETHODCALLTYPE*)(IUnknown*); + + CreateDevice_t o_CreateDevice = nullptr; + CreateDeviceEx_t o_CreateDeviceEx = nullptr; + DeviceRelease_t o_DeviceRelease = nullptr; + CreateTexture_t o_CreateTexture = nullptr; + CreateVolumeTexture_t o_CreateVolumeTexture = nullptr; + CreateCubeTexture_t o_CreateCubeTexture = nullptr; + UpdateTexture_t o_UpdateTexture = nullptr; + BeginScene_t o_BeginScene = nullptr; + SetTexture_t o_SetTexture = nullptr; + GetTexture_t o_GetTexture = nullptr; + ResourceRelease_t o_Tex2DRelease = nullptr; + ResourceRelease_t o_VolumeRelease = nullptr; + ResourceRelease_t o_CubeRelease = nullptr; + + // A vtable is shared by every instance of its class, so each is hooked once. + bool g_d3d9_hooks_installed = false; + bool g_device_hooks_installed = false; + bool g_tex2d_release_installed = false; + bool g_volume_release_installed = false; + bool g_cube_release_installed = false; + + std::vector g_hooked_targets; + + // device -> owning TextureClient + std::mutex g_devices_mutex; + std::unordered_map g_devices; + + TextureClient* ClientFor(IDirect3DDevice9* device) + { + std::lock_guard lk(g_devices_mutex); + const auto it = g_devices.find(device); + return it != g_devices.end() ? it->second : nullptr; + } + + bool HookRaw(void* target, void* detour, void** original) + { + if (target == nullptr) return false; + if (MH_CreateHook(target, detour, original) != MH_OK) { + Warning("D3D9Hooks: MH_CreateHook failed for %p\n", target); + return false; + } + if (MH_EnableHook(target) != MH_OK) { + Warning("D3D9Hooks: MH_EnableHook failed for %p\n", target); + return false; + } + g_hooked_targets.push_back(target); + return true; + } + + // Funnels the fn-ptr <-> void* casts through one spot so call sites stay /WX-clean. + template + bool Hook(void* target, TDetour detour, TOrig* original) + { + return HookRaw(target, reinterpret_cast(detour), reinterpret_cast(original)); + } + + HRESULT STDMETHODCALLTYPE h_CreateDevice(IDirect3D9*, UINT, D3DDEVTYPE, HWND, DWORD, D3DPRESENT_PARAMETERS*, IDirect3DDevice9**); + HRESULT STDMETHODCALLTYPE h_CreateDeviceEx(IDirect3D9Ex*, UINT, D3DDEVTYPE, HWND, DWORD, D3DPRESENT_PARAMETERS*, D3DDISPLAYMODEEX*, IDirect3DDevice9Ex**); + ULONG STDMETHODCALLTYPE h_DeviceRelease(IDirect3DDevice9*); + HRESULT STDMETHODCALLTYPE h_CreateTexture(IDirect3DDevice9*, UINT, UINT, UINT, DWORD, D3DFORMAT, D3DPOOL, IDirect3DTexture9**, HANDLE*); + HRESULT STDMETHODCALLTYPE h_CreateVolumeTexture(IDirect3DDevice9*, UINT, UINT, UINT, UINT, DWORD, D3DFORMAT, D3DPOOL, IDirect3DVolumeTexture9**, HANDLE*); + HRESULT STDMETHODCALLTYPE h_CreateCubeTexture(IDirect3DDevice9*, UINT, UINT, DWORD, D3DFORMAT, D3DPOOL, IDirect3DCubeTexture9**, HANDLE*); + HRESULT STDMETHODCALLTYPE h_UpdateTexture(IDirect3DDevice9*, IDirect3DBaseTexture9*, IDirect3DBaseTexture9*); + HRESULT STDMETHODCALLTYPE h_BeginScene(IDirect3DDevice9*); + HRESULT STDMETHODCALLTYPE h_SetTexture(IDirect3DDevice9*, DWORD, IDirect3DBaseTexture9*); + HRESULT STDMETHODCALLTYPE h_GetTexture(IDirect3DDevice9*, DWORD, IDirect3DBaseTexture9**); + ULONG STDMETHODCALLTYPE h_Tex2DRelease(IUnknown*); + ULONG STDMETHODCALLTYPE h_VolumeRelease(IUnknown*); + ULONG STDMETHODCALLTYPE h_CubeRelease(IUnknown*); + + void InstallDeviceHooks(IDirect3DDevice9* device) + { + if (g_device_hooks_installed) return; + void** vt = GetVTable(device); + Hook(vt[kDevice_Release], &h_DeviceRelease, reinterpret_cast(&o_DeviceRelease)); + Hook(vt[kDevice_CreateTexture], &h_CreateTexture, reinterpret_cast(&o_CreateTexture)); + Hook(vt[kDevice_CreateVolumeTexture], &h_CreateVolumeTexture, reinterpret_cast(&o_CreateVolumeTexture)); + Hook(vt[kDevice_CreateCubeTexture], &h_CreateCubeTexture, reinterpret_cast(&o_CreateCubeTexture)); + Hook(vt[kDevice_UpdateTexture], &h_UpdateTexture, reinterpret_cast(&o_UpdateTexture)); + Hook(vt[kDevice_BeginScene], &h_BeginScene, reinterpret_cast(&o_BeginScene)); + Hook(vt[kDevice_GetTexture], &h_GetTexture, reinterpret_cast(&o_GetTexture)); + Hook(vt[kDevice_SetTexture], &h_SetTexture, reinterpret_cast(&o_SetTexture)); + g_device_hooks_installed = true; + } + + // A texture vtable is reachable only via an instance, so hook Release lazily per kind. + void InstallTextureReleaseHook(void* sample_texture, TexType type) + { + void** vt = GetVTable(sample_texture); + switch (type) { + case TexType::Tex2D: + if (!g_tex2d_release_installed && Hook(vt[kResource_Release], &h_Tex2DRelease, reinterpret_cast(&o_Tex2DRelease))) + g_tex2d_release_installed = true; + break; + case TexType::Volume: + if (!g_volume_release_installed && Hook(vt[kResource_Release], &h_VolumeRelease, reinterpret_cast(&o_VolumeRelease))) + g_volume_release_installed = true; + break; + case TexType::Cube: + if (!g_cube_release_installed && Hook(vt[kResource_Release], &h_CubeRelease, reinterpret_cast(&o_CubeRelease))) + g_cube_release_installed = true; + break; + } + } + + void OnDeviceCreated(IDirect3DDevice9* device) + { + if (device == nullptr) return; + + TextureClient* client = nullptr; + { + // Lock spans check+install+create so racing callers can't double-register. + std::lock_guard lk(g_devices_mutex); + if (g_devices.contains(device)) return; + InstallDeviceHooks(device); + client = new TextureClient(device); + g_devices.emplace(device, client); + } + client->Initialize(); + } + + HRESULT STDMETHODCALLTYPE h_CreateDevice(IDirect3D9* self, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, + D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface) + { + const HRESULT hr = o_CreateDevice(self, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface); + if (SUCCEEDED(hr) && ppReturnedDeviceInterface && *ppReturnedDeviceInterface) { + OnDeviceCreated(*ppReturnedDeviceInterface); + } + return hr; + } + + HRESULT STDMETHODCALLTYPE h_CreateDeviceEx(IDirect3D9Ex* self, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, + D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode, IDirect3DDevice9Ex** ppReturnedDeviceInterface) + { + const HRESULT hr = o_CreateDeviceEx(self, Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, pFullscreenDisplayMode, ppReturnedDeviceInterface); + if (SUCCEEDED(hr) && ppReturnedDeviceInterface && *ppReturnedDeviceInterface) { + OnDeviceCreated(*ppReturnedDeviceInterface); + } + return hr; + } + + ULONG STDMETHODCALLTYPE h_DeviceRelease(IDirect3DDevice9* self) + { + const ULONG count = o_DeviceRelease(self); + if (count == 0) { + TextureClient* client = nullptr; + { + std::lock_guard lk(g_devices_mutex); + const auto it = g_devices.find(self); + if (it != g_devices.end()) { + client = it->second; + g_devices.erase(it); + } + } + delete client; // ~TextureClient drops all side-state + } + return count; + } + + HRESULT STDMETHODCALLTYPE h_CreateTexture(IDirect3DDevice9* self, UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, + IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle) + { + const HRESULT hr = o_CreateTexture(self, Width, Height, Levels, Usage, Format, Pool, ppTexture, pSharedHandle); + if (SUCCEEDED(hr) && ppTexture && *ppTexture) { + InstallTextureReleaseHook(*ppTexture, TexType::Tex2D); + if (auto* client = ClientFor(self)) + client->OnCreateTexture(static_cast(*ppTexture), TexType::Tex2D); + } + return hr; + } + + HRESULT STDMETHODCALLTYPE h_CreateVolumeTexture(IDirect3DDevice9* self, UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, + IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) + { + const HRESULT hr = o_CreateVolumeTexture(self, Width, Height, Depth, Levels, Usage, Format, Pool, ppVolumeTexture, pSharedHandle); + if (SUCCEEDED(hr) && ppVolumeTexture && *ppVolumeTexture) { + InstallTextureReleaseHook(*ppVolumeTexture, TexType::Volume); + if (auto* client = ClientFor(self)) + client->OnCreateTexture(static_cast(*ppVolumeTexture), TexType::Volume); + } + return hr; + } + + HRESULT STDMETHODCALLTYPE h_CreateCubeTexture(IDirect3DDevice9* self, UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, + IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) + { + const HRESULT hr = o_CreateCubeTexture(self, EdgeLength, Levels, Usage, Format, Pool, ppCubeTexture, pSharedHandle); + if (SUCCEEDED(hr) && ppCubeTexture && *ppCubeTexture) { + InstallTextureReleaseHook(*ppCubeTexture, TexType::Cube); + if (auto* client = ClientFor(self)) + client->OnCreateTexture(static_cast(*ppCubeTexture), TexType::Cube); + } + return hr; + } + + HRESULT STDMETHODCALLTYPE h_UpdateTexture(IDirect3DDevice9* self, IDirect3DBaseTexture9* pSourceTexture, IDirect3DBaseTexture9* pDestinationTexture) + { + // Pass the real textures through, then re-evaluate mods on the changed destination. + const HRESULT hr = o_UpdateTexture(self, pSourceTexture, pDestinationTexture); + if (SUCCEEDED(hr)) { + if (auto* client = ClientFor(self)) + client->OnUpdateTexture(pSourceTexture, pDestinationTexture); + } + return hr; + } + + HRESULT STDMETHODCALLTYPE h_BeginScene(IDirect3DDevice9* self) + { + if (auto* client = ClientFor(self)) + client->OnBeginScene(); + return o_BeginScene(self); + } + + HRESULT STDMETHODCALLTYPE h_SetTexture(IDirect3DDevice9* self, DWORD Stage, IDirect3DBaseTexture9* pTexture) + { + IDirect3DBaseTexture9* bind = pTexture; + if (auto* client = ClientFor(self)) + bind = client->ResolveBinding(pTexture); // substitute the fake when modded + return o_SetTexture(self, Stage, bind); + } + + HRESULT STDMETHODCALLTYPE h_GetTexture(IDirect3DDevice9* self, DWORD Stage, IDirect3DBaseTexture9** ppTexture) + { + const HRESULT hr = o_GetTexture(self, Stage, ppTexture); + if (SUCCEEDED(hr) && ppTexture && *ppTexture) { + if (auto* client = ClientFor(self)) { + if (auto* original = client->ResolveOriginalFromFake(*ppTexture)) { + (*ppTexture)->Release(); // drop the fake reference the runtime handed back + original->AddRef(); // return the original the game set, with a matching ref + *ppTexture = original; + } + } + } + return hr; + } + + void ReleaseTextureCleanup(IUnknown* self, ULONG count) + { + if (count != 0) return; + if (auto* client = TextureClient::CurrentClient()) + client->OnReleaseTexture(reinterpret_cast(self)); + } + + ULONG STDMETHODCALLTYPE h_Tex2DRelease(IUnknown* self) + { + const ULONG count = o_Tex2DRelease(self); + ReleaseTextureCleanup(self, count); + return count; + } + + ULONG STDMETHODCALLTYPE h_VolumeRelease(IUnknown* self) + { + const ULONG count = o_VolumeRelease(self); + ReleaseTextureCleanup(self, count); + return count; + } + + ULONG STDMETHODCALLTYPE h_CubeRelease(IUnknown* self) + { + const ULONG count = o_CubeRelease(self); + ReleaseTextureCleanup(self, count); + return count; + } +} + +void InstallD3D9Hooks(IDirect3D9* d3d9, const bool is_ex) +{ + if (d3d9 == nullptr || g_d3d9_hooks_installed) return; + void** vt = GetVTable(d3d9); + Hook(vt[kIDirect3D9_CreateDevice], &h_CreateDevice, reinterpret_cast(&o_CreateDevice)); + if (is_ex) { + Hook(vt[kIDirect3D9Ex_CreateDeviceEx], &h_CreateDeviceEx, reinterpret_cast(&o_CreateDeviceEx)); + } + g_d3d9_hooks_installed = true; +} + +bool RegisterExistingDevice(IDirect3DDevice9* device) +{ + if (device == nullptr) return false; + { + std::lock_guard lk(g_devices_mutex); + if (g_devices.contains(device)) return false; // already known + if (!g_devices.empty()) return false; // gMod supports a single device at a time + } + OnDeviceCreated(device); // installs device hooks + TextureClient (idempotent) + return ClientFor(device) != nullptr; +} + +void RemoveAllD3D9Hooks() +{ + for (void* target : g_hooked_targets) { + MH_DisableHook(target); + MH_RemoveHook(target); + } + g_hooked_targets.clear(); + + g_d3d9_hooks_installed = false; + g_device_hooks_installed = false; + g_tex2d_release_installed = false; + g_volume_release_installed = false; + g_cube_release_installed = false; + + o_CreateDevice = nullptr; + o_CreateDeviceEx = nullptr; + o_DeviceRelease = nullptr; + o_CreateTexture = nullptr; + o_CreateVolumeTexture = nullptr; + o_CreateCubeTexture = nullptr; + o_UpdateTexture = nullptr; + o_BeginScene = nullptr; + o_SetTexture = nullptr; + o_GetTexture = nullptr; + o_Tex2DRelease = nullptr; + o_VolumeRelease = nullptr; + o_CubeRelease = nullptr; +} + +// All three read state->real directly; gMod never swaps the underlying resource. + +namespace { + + HashTuple HashBits(const void* bits, const int size) + { + const auto data = static_cast(bits); + const auto crc32 = TextureFunction::get_crc32(data, size); + const auto crc64 = HashCheck::Use64BitCrc() ? TextureFunction::get_crc64(data, size) : 0; + return {crc32, crc64}; + } + + HashTuple HashTexture2D(const TexState* state) + { + const auto pTexture = static_cast(state->real); + IDirect3DDevice9* device = state->device; + + IDirect3DSurface9* pOffscreenSurface = nullptr; + IDirect3DSurface9* pResolvedSurface = nullptr; + D3DLOCKED_RECT d3dlr; + D3DSURFACE_DESC desc; + + if (pTexture->GetLevelDesc(0, &desc) != D3D_OK) { + Warning("GetTextureHash(2D) Failed: GetLevelDesc\n"); + return {}; + } + + if (desc.Pool == D3DPOOL_DEFAULT) { + IDirect3DSurface9* pSurfaceLevel_orig = nullptr; + if (pTexture->GetSurfaceLevel(0, &pSurfaceLevel_orig) != D3D_OK) { + Warning("GetTextureHash(2D) Failed: GetSurfaceLevel 1 (D3DPOOL_DEFAULT)\n"); + return {}; + } + + if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) { + if (D3D_OK != device->CreateRenderTarget(desc.Width, desc.Height, desc.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pResolvedSurface, nullptr)) { + pSurfaceLevel_orig->Release(); + Warning("GetTextureHash(2D) Failed: CreateRenderTarget (D3DPOOL_DEFAULT)\n"); + return {}; + } + if (D3D_OK != device->StretchRect(pSurfaceLevel_orig, nullptr, pResolvedSurface, nullptr, D3DTEXF_NONE)) { + pSurfaceLevel_orig->Release(); + Warning("GetTextureHash(2D) Failed: StretchRect (D3DPOOL_DEFAULT)\n"); + return {}; + } + pSurfaceLevel_orig = pResolvedSurface; + } + + if (D3D_OK != device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pOffscreenSurface, nullptr)) { + pSurfaceLevel_orig->Release(); + if (pResolvedSurface != nullptr) pResolvedSurface->Release(); + Warning("GetTextureHash(2D) Failed: CreateOffscreenPlainSurface (D3DPOOL_DEFAULT)\n"); + return {}; + } + + if (D3D_OK != device->GetRenderTargetData(pSurfaceLevel_orig, pOffscreenSurface)) { + pSurfaceLevel_orig->Release(); + if (pResolvedSurface != nullptr) pResolvedSurface->Release(); + pOffscreenSurface->Release(); + Warning("GetTextureHash(2D) Failed: GetRenderTargetData (D3DPOOL_DEFAULT)\n"); + return {}; + } + pSurfaceLevel_orig->Release(); + + if (pOffscreenSurface->LockRect(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) { + if (pResolvedSurface != nullptr) pResolvedSurface->Release(); + pOffscreenSurface->Release(); + Warning("GetTextureHash(2D) Failed: LockRect (D3DPOOL_DEFAULT)\n"); + return {}; + } + } + else if (pTexture->LockRect(0, &d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) { + Warning("GetTextureHash(2D) Failed: LockRect 1\n"); + if (pTexture->GetSurfaceLevel(0, &pResolvedSurface) != D3D_OK) { + Warning("GetTextureHash(2D) Failed: GetSurfaceLevel\n"); + return {}; + } + if (pResolvedSurface->LockRect(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) { + pResolvedSurface->Release(); + Warning("GetTextureHash(2D) Failed: LockRect 2\n"); + return {}; + } + } + + const int size = (TextureFunction::GetBitsFromFormat(desc.Format) * desc.Width * desc.Height) / 8; + const auto hash = HashBits(d3dlr.pBits, size); + + if (pOffscreenSurface != nullptr) { + pOffscreenSurface->UnlockRect(); + pOffscreenSurface->Release(); + if (pResolvedSurface != nullptr) pResolvedSurface->Release(); + } + else if (pResolvedSurface != nullptr) { + pResolvedSurface->UnlockRect(); + pResolvedSurface->Release(); + } + else { + pTexture->UnlockRect(0); + } + + return hash; + } + + HashTuple HashVolume(const TexState* state) + { + const auto pTexture = static_cast(state->real); + + IDirect3DVolume9* pResolvedSurface = nullptr; + D3DLOCKED_BOX d3dlr; + D3DVOLUME_DESC desc; + + if (pTexture->GetLevelDesc(0, &desc) != D3D_OK) { + Warning("GetTextureHash(Volume) Failed: GetLevelDesc\n"); + return {}; + } + + if (pTexture->LockBox(0, &d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) { + if (pTexture->GetVolumeLevel(0, &pResolvedSurface) != D3D_OK) { + Warning("GetTextureHash(Volume) Failed: GetVolumeLevel\n"); + return {}; + } + if (pResolvedSurface->LockBox(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) { + pResolvedSurface->Release(); + Warning("GetTextureHash(Volume) Failed: LockBox\n"); + return {}; + } + } + + const int size = (TextureFunction::GetBitsFromFormat(desc.Format) * desc.Width * desc.Height * desc.Depth) / 8; + const auto hash = HashBits(d3dlr.pBits, size); + + if (pResolvedSurface != nullptr) { + pResolvedSurface->UnlockBox(); + pResolvedSurface->Release(); + } + else { + pTexture->UnlockBox(0); + } + + return hash; + } + + HashTuple HashCube(const TexState* state) + { + const auto pTexture = static_cast(state->real); + + IDirect3DSurface9* pResolvedSurface = nullptr; + D3DLOCKED_RECT d3dlr; + D3DSURFACE_DESC desc; + + if (pTexture->GetLevelDesc(0, &desc) != D3D_OK) { + Warning("GetTextureHash(Cube) Failed: GetLevelDesc\n"); + return {}; + } + + if (pTexture->LockRect(D3DCUBEMAP_FACE_POSITIVE_X, 0, &d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) { + if (pTexture->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_X, 0, &pResolvedSurface) != D3D_OK) { + Warning("GetTextureHash(Cube) Failed: GetCubeMapSurface\n"); + return {}; + } + if (pResolvedSurface->LockRect(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) { + pResolvedSurface->Release(); + Warning("GetTextureHash(Cube) Failed: LockRect\n"); + return {}; + } + } + + const int size = (TextureFunction::GetBitsFromFormat(desc.Format) * desc.Width * desc.Height) / 8; + const auto hash = HashBits(d3dlr.pBits, size); + + if (pResolvedSurface != nullptr) { + pResolvedSurface->UnlockRect(); + pResolvedSurface->Release(); + } + else { + pTexture->UnlockRect(D3DCUBEMAP_FACE_POSITIVE_X, 0); + } + + return hash; + } +} + +HashTuple GetTextureHash(const TexState* state) +{ + if (state == nullptr || state->real == nullptr || state->isFake) return {}; + switch (state->type) { + case TexType::Tex2D: return HashTexture2D(state); + case TexType::Volume: return HashVolume(state); + case TexType::Cube: return HashCube(state); + } + return {}; +} diff --git a/source/Error.cpp b/source/Error.cpp index 5b24500..434f29b 100644 --- a/source/Error.cpp +++ b/source/Error.cpp @@ -6,10 +6,10 @@ #include __declspec(noreturn) void FatalAssert( -const char *expr, -const char *file, -unsigned int line, -const char *function) + const char* expr, + const char* file, + unsigned int line, + const char* function) { char module_path[MAX_PATH]{}; if (gl_hThisInstance) { @@ -21,7 +21,7 @@ const char *function) const char* fmt = "Module: %s\n\nExpr: %s\n\nFile: %s\n\nFunction: %s, line %d"; int len = snprintf(NULL, 0, fmt, module_path, expr, file, function, line); char* buf = new char[len + 1]; - snprintf(buf,len + 1, fmt, module_path, expr, file, function, line); + snprintf(buf, len + 1, fmt, module_path, expr, file, function, line); MessageBox(0, buf, "uMod Assertion Failure", MB_OK | MB_ICONERROR); diff --git a/source/dll_main.cpp b/source/dll_main.cpp index aa8f57b..ffc52f6 100644 --- a/source/dll_main.cpp +++ b/source/dll_main.cpp @@ -1,6 +1,7 @@ #include "Main.h" #include #include "MinHook.h" +#include "D3D9Hooks.h" import TextureClient; @@ -9,9 +10,10 @@ void InitInstance(HINSTANCE hModule); namespace { - #define DISABLE_HOOK(var) if(var) { MH_DisableHook(var);} +#define DISABLE_HOOK(var) \ + if (var) { MH_DisableHook(var); } - using Direct3DCreate9_type = IDirect3D9* (APIENTRY*)(UINT); + using Direct3DCreate9_type = IDirect3D9*(APIENTRY*)(UINT); using Direct3DCreate9Ex_type = HRESULT(APIENTRY*)(UINT SDKVersion, IDirect3D9Ex** ppD3D); using GetProcAddress_type = FARPROC(APIENTRY*)(HMODULE, LPCSTR); @@ -65,15 +67,14 @@ namespace { const auto exe_path = std::filesystem::path(executable_path); const auto gmod_path = std::filesystem::path(dll_path); - if (exe_path.parent_path() != gmod_path.parent_path() - || gmod_path.filename() != "d3d9.dll") { + if (exe_path.parent_path() != gmod_path.parent_path() || gmod_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"); } if (!gMod_Loaded_d3d9_Module_Handle) { // Tried resolving d3d9.dll locally, didn't work. Try system directory char buffer[MAX_PATH]; - ASSERT(GetSystemDirectory(buffer, _countof(buffer)) > 0); //get the system directory, we need to open the original d3d9.dll + 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"); @@ -141,12 +142,14 @@ IDirect3D9* APIENTRY Direct3DCreate9(UINT SDKVersion) DISABLE_HOOK(GetProcAddress_fn); CheckLoadD3d9Dll(); - IDirect3D9* pIDirect3D9_orig = Direct3DCreate9_ret(SDKVersion); //creating the original IDirect3D9 object + IDirect3D9* pIDirect3D9_orig = Direct3DCreate9_ret(SDKVersion); // creating the original IDirect3D9 object ASSERT(pIDirect3D9_orig); creating_d3d9 = false; - return new uMod_IDirect3D9(pIDirect3D9_orig); //return our object instead of the "real one" + // Hook the vtable and hand the game back the real object untouched. + InstallD3D9Hooks(pIDirect3D9_orig, false); + return pIDirect3D9_orig; } HRESULT APIENTRY Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex** ppD3D) @@ -161,17 +164,16 @@ HRESULT APIENTRY Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex** ppD3D) CheckLoadD3d9Dll(); IDirect3D9Ex* pIDirect3D9Ex_orig = nullptr; - HRESULT ret = Direct3DCreate9Ex_ret(SDKVersion, &pIDirect3D9Ex_orig); //creating the original IDirect3D9 object + HRESULT ret = Direct3DCreate9Ex_ret(SDKVersion, &pIDirect3D9Ex_orig); // creating the original IDirect3D9 object creating_d3d9 = false; if (ret != S_OK) return ret; - // @Cleanup: should be we freeing pIDirect3D9Ex at the end of our own lifecycle? - const auto pIDirect3D9Ex = new uMod_IDirect3D9Ex(pIDirect3D9Ex_orig); - // original umod does not do this for some reason - *ppD3D = static_cast(pIDirect3D9Ex); + // Hook the vtable (CreateDevice + CreateDeviceEx) and return the real object untouched. + InstallD3D9Hooks(pIDirect3D9Ex_orig, true); + *ppD3D = pIDirect3D9Ex_orig; return ret; } @@ -210,9 +212,9 @@ void LoadModlists() { Message("Initialize: searching for modlist.txt\n"); char gwpath[MAX_PATH]{}; - GetModuleFileName(GetModuleHandle(nullptr), gwpath, MAX_PATH); //ask for name and path of this executable + GetModuleFileName(GetModuleHandle(nullptr), gwpath, MAX_PATH); // ask for name and path of this executable char dllpath[MAX_PATH]{}; - GetModuleFileName(gl_hThisInstance, dllpath, MAX_PATH); //ask for name and path of this dll + GetModuleFileName(gl_hThisInstance, dllpath, MAX_PATH); // ask for name and path of this dll const auto exe_path = std::filesystem::path(gwpath).parent_path(); const auto dll_path = std::filesystem::path(dllpath).parent_path(); for (const auto& path : {exe_path, dll_path}) { @@ -235,11 +237,11 @@ void InitInstance(HINSTANCE hModule) gl_hThisInstance = hModule; LoadModlists(); - DisableThreadLibraryCalls(hModule); //reduce overhead + DisableThreadLibraryCalls(hModule); // reduce overhead // d3d9.dll shouldn't be loaded at this point. [[maybe_unused]] const auto d3d9_loaded = FindLoadedModuleByName("d3d9.dll"); - //ASSERT(!d3d9_loaded); + // ASSERT(!d3d9_loaded); MH_Initialize(); @@ -252,6 +254,20 @@ void InitInstance(HINSTANCE hModule) } } +// Exported entry for late injection: hand gMod a device that already exists +// (IDirect3DDevice9Ex* works too) so it hooks the vtable and mods textures from +// here on. Returns RETURN_OK if newly registered, RETURN_EXISTS if already known. +extern "C" __declspec(dllexport) int __cdecl SetDevice(IDirect3DDevice9* device) +{ + if (!device) return RETURN_BAD_ARGUMENT; + try { + return RegisterExistingDevice(device) ? RETURN_OK : RETURN_EXISTS; + } + catch (...) { + return RETURN_FATAL_ERROR; + } +} + extern "C" __declspec(dllexport) int __cdecl AddFile(const wchar_t* path) { if (!path) return RETURN_BAD_ARGUMENT; @@ -276,6 +292,7 @@ extern "C" __declspec(dllexport) int __cdecl RemoveFile(const wchar_t* path) // nullptr first arg = return required size // returns paths separated by null terminator, e.g. "C:\foo.tpf\0C:\bar.zip\0\0" +// Paths come back in load order (== priority order). extern "C" __declspec(dllexport) int __cdecl GetFiles(wchar_t* buffer, const size_t buffer_size_chars) { try { @@ -306,6 +323,9 @@ void ExitInstance() { DISABLE_HOOK(GetProcAddress_fn); + // Revert every D3D9 vtable hook so the original objects are left pristine. + RemoveAllD3D9Hooks(); + MH_Uninitialize(); if (gMod_Loaded_d3d9_Module_Handle) @@ -319,6 +339,7 @@ void ExitInstance() __try { FreeConsole(); } - __except (EXCEPTION_CONTINUE_EXECUTION) { } + __except (EXCEPTION_CONTINUE_EXECUTION) { + } #endif } diff --git a/source/uMod_IDirect3D9.cpp b/source/uMod_IDirect3D9.cpp deleted file mode 100644 index 5e85215..0000000 --- a/source/uMod_IDirect3D9.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "Main.h" - -#ifndef PRE_MESSAGE -#define PRE_MESSAGE "uMod_IDirect3D9" -#endif - -uMod_IDirect3D9::uMod_IDirect3D9(IDirect3D9* pOriginal) -{ - Message(PRE_MESSAGE "::" PRE_MESSAGE " (%p): %p\n", pOriginal, this); - m_pIDirect3D9 = pOriginal; -} - -uMod_IDirect3D9::~uMod_IDirect3D9() -{ - Message(PRE_MESSAGE "::~" PRE_MESSAGE "(): %p\n", this); -} - -HRESULT __stdcall uMod_IDirect3D9::QueryInterface(REFIID riid, void** ppvObj) -{ - *ppvObj = nullptr; - - // call this to increase AddRef at original object - // and to check if such an interface is there - - const HRESULT hRes = m_pIDirect3D9->QueryInterface(riid, ppvObj); - - if (hRes == NOERROR) // if OK, send our "fake" address - { - *ppvObj = this; - } - - return hRes; -} - -ULONG __stdcall uMod_IDirect3D9::AddRef() -{ - return m_pIDirect3D9->AddRef(); -} - -ULONG __stdcall uMod_IDirect3D9::Release() -{ - // call original routine - const ULONG count = m_pIDirect3D9->Release(); - - // in case no further Ref is there, the Original Object has deleted itself - if (count == 0) { - delete this; - } - - return count; -} - -HRESULT __stdcall uMod_IDirect3D9::RegisterSoftwareDevice(void* pInitializeFunction) -{ - return m_pIDirect3D9->RegisterSoftwareDevice(pInitializeFunction); -} - -UINT __stdcall uMod_IDirect3D9::GetAdapterCount() -{ - return m_pIDirect3D9->GetAdapterCount(); -} - -HRESULT __stdcall uMod_IDirect3D9::GetAdapterIdentifier(UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) -{ - return m_pIDirect3D9->GetAdapterIdentifier(Adapter, Flags, pIdentifier); -} - -UINT __stdcall uMod_IDirect3D9::GetAdapterModeCount(UINT Adapter, D3DFORMAT Format) -{ - return m_pIDirect3D9->GetAdapterModeCount(Adapter, Format); -} - -HRESULT __stdcall uMod_IDirect3D9::EnumAdapterModes(UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) -{ - return m_pIDirect3D9->EnumAdapterModes(Adapter, Format, Mode, pMode); -} - -HRESULT __stdcall uMod_IDirect3D9::GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE* pMode) -{ - return m_pIDirect3D9->GetAdapterDisplayMode(Adapter, pMode); -} - -HRESULT __stdcall uMod_IDirect3D9::CheckDeviceType(UINT iAdapter, D3DDEVTYPE DevType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed) -{ - return m_pIDirect3D9->CheckDeviceType(iAdapter, DevType, DisplayFormat, BackBufferFormat, bWindowed); -} - -HRESULT __stdcall uMod_IDirect3D9::CheckDeviceFormat(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) -{ - return m_pIDirect3D9->CheckDeviceFormat(Adapter, DeviceType, AdapterFormat, Usage, RType, CheckFormat); -} - -HRESULT __stdcall uMod_IDirect3D9::CheckDeviceMultiSampleType(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) -{ - return m_pIDirect3D9->CheckDeviceMultiSampleType(Adapter, DeviceType, SurfaceFormat, Windowed, MultiSampleType, pQualityLevels); -} - -HRESULT __stdcall uMod_IDirect3D9::CheckDepthStencilMatch(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) -{ - return m_pIDirect3D9->CheckDepthStencilMatch(Adapter, DeviceType, AdapterFormat, RenderTargetFormat, DepthStencilFormat); -} - -HRESULT __stdcall uMod_IDirect3D9::CheckDeviceFormatConversion(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) -{ - return m_pIDirect3D9->CheckDeviceFormatConversion(Adapter, DeviceType, SourceFormat, TargetFormat); -} - -HRESULT __stdcall uMod_IDirect3D9::GetDeviceCaps(UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) -{ - return m_pIDirect3D9->GetDeviceCaps(Adapter, DeviceType, pCaps); -} - -HMONITOR __stdcall uMod_IDirect3D9::GetAdapterMonitor(UINT Adapter) -{ - return m_pIDirect3D9->GetAdapterMonitor(Adapter); -} - -HRESULT __stdcall uMod_IDirect3D9::CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface) -{ - Message(PRE_MESSAGE "::CreateDevice(): %p\n", this); - // we intercept this call and provide our own "fake" Device Object - const HRESULT hres = m_pIDirect3D9->CreateDevice(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface); - - int count = 1; - if (pPresentationParameters != nullptr) { - count = pPresentationParameters->BackBufferCount; - } - const auto pIDirect3DDevice9 = new uMod_IDirect3DDevice9(*ppReturnedDeviceInterface, count); - - // store our pointer (the fake one) for returning it to the calling program - *ppReturnedDeviceInterface = pIDirect3DDevice9; - - return hres; -} diff --git a/source/uMod_IDirect3D9Ex.cpp b/source/uMod_IDirect3D9Ex.cpp deleted file mode 100644 index f5c23b2..0000000 --- a/source/uMod_IDirect3D9Ex.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "Main.h" - -#define IDirect3D9 IDirect3D9Ex -#define uMod_IDirect3D9 uMod_IDirect3D9Ex -#define m_pIDirect3D9 m_pIDirect3D9Ex -#define PRE_MESSAGE "uMod_IDirect3D9Ex" - -// ReSharper disable once CppUnusedIncludeDirective -#include "uMod_IDirect3D9.cpp" - -HRESULT __stdcall uMod_IDirect3D9Ex::CreateDeviceEx(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode, - IDirect3DDevice9Ex** ppReturnedDeviceInterface) -{ - Message("uMod_IDirect3D9Ex::CreateDeviceEx: %p\n", this); - // we intercept this call and provide our own "fake" Device Object - const HRESULT hres = m_pIDirect3D9Ex->CreateDeviceEx(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, pFullscreenDisplayMode, ppReturnedDeviceInterface); - - int count = 1; - if (pPresentationParameters != nullptr) { - count = pPresentationParameters->BackBufferCount; - } - const auto pIDirect3DDevice9Ex = new uMod_IDirect3DDevice9Ex(*ppReturnedDeviceInterface, count); - - // store our pointer (the fake one) for returning it to the calling program - *ppReturnedDeviceInterface = pIDirect3DDevice9Ex; - - return hres; -} - -HRESULT __stdcall uMod_IDirect3D9Ex::EnumAdapterModesEx(UINT Adapter, const D3DDISPLAYMODEFILTER* pFilter, UINT Mode, D3DDISPLAYMODEEX* pMode) -{ - return m_pIDirect3D9Ex->EnumAdapterModesEx(Adapter, pFilter, Mode, pMode); -} - -HRESULT __stdcall uMod_IDirect3D9Ex::GetAdapterDisplayModeEx(UINT Adapter, D3DDISPLAYMODEEX* pMode, D3DDISPLAYROTATION* pRotation) -{ - return m_pIDirect3D9Ex->GetAdapterDisplayModeEx(Adapter, pMode, pRotation); -} - -HRESULT __stdcall uMod_IDirect3D9Ex::GetAdapterLUID(UINT Adapter, LUID* pLUID) -{ - return m_pIDirect3D9Ex->GetAdapterLUID(Adapter, pLUID); -} - -UINT __stdcall uMod_IDirect3D9Ex::GetAdapterModeCountEx(UINT Adapter, const D3DDISPLAYMODEFILTER* pFilter) -{ - return m_pIDirect3D9Ex->GetAdapterModeCountEx(Adapter, pFilter); -} diff --git a/source/uMod_IDirect3DCubeTexture9.cpp b/source/uMod_IDirect3DCubeTexture9.cpp deleted file mode 100644 index eb110b9..0000000 --- a/source/uMod_IDirect3DCubeTexture9.cpp +++ /dev/null @@ -1,283 +0,0 @@ -#include "Main.h" - -import ModfileLoader; -import TextureClient; -import TextureFunction; - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DCubeTexture9::QueryInterface(REFIID riid, void** ppvObj) -{ - if (riid == IID_IDirect3D9) { - // This function should never be called with IID_IDirect3D9 by the game - // thus this call comes from our own dll to ask for the texture type - // 0x01000000L == uMod_IDirect3DTexture9 - // 0x01000001L == uMod_IDirect3DVolumeTexture9 - // 0x01000002L == uMod_IDirect3DCubeTexture9 - - *ppvObj = this; - return 0x01000002L; - } - HRESULT hRes; - if (CrossRef_D3Dtex != nullptr) { - hRes = CrossRef_D3Dtex->m_D3Dtex->QueryInterface(riid, ppvObj); - if (*ppvObj == CrossRef_D3Dtex->m_D3Dtex) { - *ppvObj = this; - } - } - else { - hRes = m_D3Dtex->QueryInterface(riid, ppvObj); - if (*ppvObj == m_D3Dtex) { - *ppvObj = this; - } - } - return hRes; -} - -//this function yields for the non switched texture object -ULONG APIENTRY uMod_IDirect3DCubeTexture9::AddRef() -{ - if (FAKE) { - return 1; //bug, this case should never happen - } - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->AddRef(); - } - return m_D3Dtex->AddRef(); -} - -//this function yields for the non switched texture object -ULONG APIENTRY uMod_IDirect3DCubeTexture9::Release() -{ - Message("uMod_IDirect3DCubeTexture9::Release(): %p\n", this); - - void* cpy; - const long ret = m_D3Ddev->QueryInterface(IID_IDirect3DTexture9, &cpy); - - ULONG count; - if (FAKE) { - UnswitchTextures(this); - count = m_D3Dtex->Release(); //count must be zero, cause we don't call AddRef of fake_textures - } - else { - if (CrossRef_D3Dtex != nullptr) //if this texture is switched with a fake texture - { - uMod_IDirect3DCubeTexture9* fake_texture = CrossRef_D3Dtex; - count = fake_texture->m_D3Dtex->Release(); //release the original texture - if (count == 0) //if texture is released we switch the textures back - { - UnswitchTextures(this); - fake_texture->Release(); // we release the fake texture - } - } - else { - count = m_D3Dtex->Release(); - } - } - - if (count == 0) //if this texture is released, we clean up - { - // if this texture is the LastCreatedTexture, the next time LastCreatedTexture would be added, - // the hash of a non existing texture would be calculated - if (ret == 0x01000000L) { - if (static_cast(m_D3Ddev)->GetLastCreatedCubeTexture() == this) { - static_cast(m_D3Ddev)->SetLastCreatedCubeTexture(nullptr); - } - else { - static_cast(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client - } - } - else { - if (static_cast(m_D3Ddev)->GetLastCreatedCubeTexture() == this) { - static_cast(m_D3Ddev)->SetLastCreatedCubeTexture(nullptr); - } - else { - static_cast(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client - } - } - - delete this; - } - return count; -} - -HRESULT APIENTRY uMod_IDirect3DCubeTexture9::GetDevice(IDirect3DDevice9** ppDevice) -{ - *ppDevice = m_D3Ddev; - return D3D_OK; -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DCubeTexture9::SetPrivateData(REFGUID refguid,CONST void* pData, DWORD SizeOfData, DWORD Flags) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->SetPrivateData(refguid, pData, SizeOfData, Flags); - } - return m_D3Dtex->SetPrivateData(refguid, pData, SizeOfData, Flags); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DCubeTexture9::GetPrivateData(REFGUID refguid, void* pData, DWORD* pSizeOfData) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->GetPrivateData(refguid, pData, pSizeOfData); - } - return m_D3Dtex->GetPrivateData(refguid, pData, pSizeOfData); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DCubeTexture9::FreePrivateData(REFGUID refguid) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->FreePrivateData(refguid); - } - return m_D3Dtex->FreePrivateData(refguid); -} - -DWORD APIENTRY uMod_IDirect3DCubeTexture9::SetPriority(DWORD PriorityNew) -{ - return m_D3Dtex->SetPriority(PriorityNew); -} - -DWORD APIENTRY uMod_IDirect3DCubeTexture9::GetPriority() -{ - return m_D3Dtex->GetPriority(); -} - -void APIENTRY uMod_IDirect3DCubeTexture9::PreLoad() -{ - m_D3Dtex->PreLoad(); -} - -D3DRESOURCETYPE APIENTRY uMod_IDirect3DCubeTexture9::GetType() -{ - return m_D3Dtex->GetType(); -} - -DWORD APIENTRY uMod_IDirect3DCubeTexture9::SetLOD(DWORD LODNew) -{ - return m_D3Dtex->SetLOD(LODNew); -} - -DWORD APIENTRY uMod_IDirect3DCubeTexture9::GetLOD() -{ - return m_D3Dtex->GetLOD(); -} - -DWORD APIENTRY uMod_IDirect3DCubeTexture9::GetLevelCount() -{ - return m_D3Dtex->GetLevelCount(); -} - -HRESULT APIENTRY uMod_IDirect3DCubeTexture9::SetAutoGenFilterType(D3DTEXTUREFILTERTYPE FilterType) -{ - return m_D3Dtex->SetAutoGenFilterType(FilterType); -} - -D3DTEXTUREFILTERTYPE APIENTRY uMod_IDirect3DCubeTexture9::GetAutoGenFilterType() -{ - return m_D3Dtex->GetAutoGenFilterType(); -} - -void APIENTRY uMod_IDirect3DCubeTexture9::GenerateMipSubLevels() -{ - m_D3Dtex->GenerateMipSubLevels(); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DCubeTexture9::AddDirtyRect(D3DCUBEMAP_FACES FaceType, CONST RECT* pDirtyRect) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->AddDirtyRect(FaceType, pDirtyRect); - } - return m_D3Dtex->AddDirtyRect(FaceType, pDirtyRect); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DCubeTexture9::GetLevelDesc(UINT Level, D3DSURFACE_DESC* pDesc) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->GetLevelDesc(Level, pDesc); - } - return m_D3Dtex->GetLevelDesc(Level, pDesc); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DCubeTexture9::GetCubeMapSurface(D3DCUBEMAP_FACES FaceType, UINT Level, IDirect3DSurface9** ppCubeMapSurface) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->GetCubeMapSurface(FaceType, Level, ppCubeMapSurface); - } - return m_D3Dtex->GetCubeMapSurface(FaceType, Level, ppCubeMapSurface); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DCubeTexture9::LockRect(D3DCUBEMAP_FACES FaceType, UINT Level, D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect, DWORD Flags) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->LockRect(FaceType, Level, pLockedRect, pRect, Flags); - } - return m_D3Dtex->LockRect(FaceType, Level, pLockedRect, pRect, Flags); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DCubeTexture9::UnlockRect(D3DCUBEMAP_FACES FaceType, UINT Level) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->UnlockRect(FaceType, Level); - } - return m_D3Dtex->UnlockRect(FaceType, Level); -} - -HashTuple uMod_IDirect3DCubeTexture9::GetHash() const -{ - if (FAKE) { - return {}; - } - IDirect3DCubeTexture9* pTexture = m_D3Dtex; - if (CrossRef_D3Dtex != nullptr) { - pTexture = CrossRef_D3Dtex->m_D3Dtex; - } - - IDirect3DSurface9* pResolvedSurface = nullptr; - D3DLOCKED_RECT d3dlr; - D3DSURFACE_DESC desc; - - if (pTexture->GetLevelDesc(0, &desc) != D3D_OK) //get the format and the size of the texture - { - Warning("uMod_IDirect3DCubeTexture9::GetHash() Failed: GetLevelDesc \n"); - return {}; - } - - Message("uMod_IDirect3DCubeTexture9::GetHash() (%d %d) %d\n", desc.Width, desc.Height, desc.Format); - - if (pTexture->LockRect(D3DCUBEMAP_FACE_POSITIVE_X, 0, &d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) - { - Warning("uMod_IDirect3DCubeTexture9::GetHash() Failed: LockRect 1\n"); - if (pTexture->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_X, 0, &pResolvedSurface) != D3D_OK) { - Warning("uMod_IDirect3DCubeTexture9::GetHash() Failed: GetSurfaceLevel\n"); - return {}; - } - if (pResolvedSurface->LockRect(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) { - pResolvedSurface->Release(); - Warning("uMod_IDirect3DCubeTexture9::GetHash() Failed: LockRect 2\n"); - return {}; - } - } - - const auto size = (TextureFunction::GetBitsFromFormat(desc.Format) * desc.Width * desc.Height) / 8; - const auto crc32 = TextureFunction::get_crc32(static_cast(d3dlr.pBits), size); - const auto crc64 = HashCheck::Use64BitCrc() ? TextureFunction::get_crc64(static_cast(d3dlr.pBits), size) : 0; - - // Only release surfaces after we're finished with d3dlr - if (pResolvedSurface != nullptr) { - pResolvedSurface->UnlockRect(); - pResolvedSurface->Release(); - } - else { - pTexture->UnlockRect(D3DCUBEMAP_FACE_POSITIVE_X, 0); //unlock the raw data - } - - Message("uMod_IDirect3DCubeTexture9::GetHash() %#lX (%d %d) %d = %d\n", crc32, desc.Width, desc.Height, desc.Format, size); - Message("uMod_IDirect3DCubeTexture9::GetHash() %#llX (%d %d) %d = %d\n", crc64, desc.Width, desc.Height, desc.Format, size); - return {crc32, crc64}; -} diff --git a/source/uMod_IDirect3DDevice9.cpp b/source/uMod_IDirect3DDevice9.cpp deleted file mode 100644 index c7b3a9e..0000000 --- a/source/uMod_IDirect3DDevice9.cpp +++ /dev/null @@ -1,914 +0,0 @@ -#include "Main.h" -import TextureClient; - -#ifndef RETURN_QueryInterface -#define RETURN_QueryInterface 0x01000000L -#endif - -#ifndef PRE_MESSAGE -#define PRE_MESSAGE "uMod_IDirect3DDevice9" -#endif - -uMod_IDirect3DDevice9::uMod_IDirect3DDevice9(IDirect3DDevice9* pOriginal, int back_buffer_count) -{ - Message(PRE_MESSAGE "::" PRE_MESSAGE " (%p): %p\n", pOriginal, this); - - BackBufferCount = back_buffer_count; - - uMod_Client = new TextureClient(this); //get a new texture client for this device - uMod_Client->Initialize(); - m_pIDirect3DDevice9 = pOriginal; // store the pointer to original object -} - -uMod_IDirect3DDevice9::~uMod_IDirect3DDevice9() -{ - Message(PRE_MESSAGE "::~" PRE_MESSAGE "(): %p\n", this); -} - -HRESULT uMod_IDirect3DDevice9::QueryInterface(REFIID riid, void** ppvObj) -{ - // check if original dll can provide interface. then send *our* address - if (riid == IID_IDirect3DTexture9) { - // This function should never be called with IDirect3DTexture9 by the game - *ppvObj = this; - return RETURN_QueryInterface; - } - - *ppvObj = nullptr; - Message(PRE_MESSAGE "::QueryInterface(): %p\n", this); - const HRESULT hRes = m_pIDirect3DDevice9->QueryInterface(riid, ppvObj); - - if (*ppvObj == m_pIDirect3DDevice9) { - uMod_Reference++; //increasing our counter - *ppvObj = this; - } - - return hRes; -} - -ULONG uMod_IDirect3DDevice9::AddRef() -{ - uMod_Reference++; //increasing our counter - Message("%p = " PRE_MESSAGE "::AddRef(): %p\n", uMod_Reference, this); - return m_pIDirect3DDevice9->AddRef(); -} - -ULONG uMod_IDirect3DDevice9::Release() -{ - if (--uMod_Reference == 0) //if our counter drops to zero, the real device will be deleted, so we clean up before - { - // we must not release the fake textures, cause they are released if the target textures are released - // and the target textures are released by the game. - - delete uMod_Client; //must be deleted at the end, because other releases might call a function of this object - uMod_Client = nullptr; - } - - const ULONG count = m_pIDirect3DDevice9->Release(); - Message("%p = " PRE_MESSAGE "::Release(): %p\n", count, this); - if (uMod_Reference != static_cast(count)) //bug - { - Message("Error in " PRE_MESSAGE "::Release(): %p!=%p\n", uMod_Reference, count); - } - - if (count == 0u) { - delete this; - } - return count; -} - -HRESULT uMod_IDirect3DDevice9::TestCooperativeLevel() -{ - return m_pIDirect3DDevice9->TestCooperativeLevel(); -} - -UINT uMod_IDirect3DDevice9::GetAvailableTextureMem() -{ - return m_pIDirect3DDevice9->GetAvailableTextureMem(); -} - -HRESULT uMod_IDirect3DDevice9::EvictManagedResources() -{ - return m_pIDirect3DDevice9->EvictManagedResources(); -} - -HRESULT uMod_IDirect3DDevice9::GetDirect3D(IDirect3D9** ppD3D9) -{ - return m_pIDirect3DDevice9->GetDirect3D(ppD3D9); -} - -HRESULT uMod_IDirect3DDevice9::GetDeviceCaps(D3DCAPS9* pCaps) -{ - return m_pIDirect3DDevice9->GetDeviceCaps(pCaps); -} - -HRESULT uMod_IDirect3DDevice9::GetDisplayMode(UINT iSwapChain, D3DDISPLAYMODE* pMode) -{ - return m_pIDirect3DDevice9->GetDisplayMode(iSwapChain, pMode); -} - -HRESULT uMod_IDirect3DDevice9::GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS* pParameters) -{ - return m_pIDirect3DDevice9->GetCreationParameters(pParameters); -} - -HRESULT uMod_IDirect3DDevice9::SetCursorProperties(UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap) -{ - return m_pIDirect3DDevice9->SetCursorProperties(XHotSpot, YHotSpot, pCursorBitmap); -} - -void uMod_IDirect3DDevice9::SetCursorPosition(int X, int Y, DWORD Flags) -{ - m_pIDirect3DDevice9->SetCursorPosition(X, Y, Flags); -} - -BOOL uMod_IDirect3DDevice9::ShowCursor(BOOL bShow) -{ - return m_pIDirect3DDevice9->ShowCursor(bShow); -} - -HRESULT uMod_IDirect3DDevice9::CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain) -{ - return m_pIDirect3DDevice9->CreateAdditionalSwapChain(pPresentationParameters, pSwapChain); -} - -HRESULT uMod_IDirect3DDevice9::GetSwapChain(UINT iSwapChain, IDirect3DSwapChain9** pSwapChain) -{ - return m_pIDirect3DDevice9->GetSwapChain(iSwapChain, pSwapChain); -} - -UINT uMod_IDirect3DDevice9::GetNumberOfSwapChains() -{ - return m_pIDirect3DDevice9->GetNumberOfSwapChains(); -} - -HRESULT uMod_IDirect3DDevice9::Reset(D3DPRESENT_PARAMETERS* pPresentationParameters) -{ - return m_pIDirect3DDevice9->Reset(pPresentationParameters); -} - -HRESULT uMod_IDirect3DDevice9::Present(CONST RECT* pSourceRect,CONST RECT* pDestRect, HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) -{ - return m_pIDirect3DDevice9->Present(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); -} - -HRESULT uMod_IDirect3DDevice9::GetBackBuffer(UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) -{ - return m_pIDirect3DDevice9->GetBackBuffer(iSwapChain, iBackBuffer, Type, ppBackBuffer); -} - -HRESULT uMod_IDirect3DDevice9::GetRasterStatus(UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) -{ - return m_pIDirect3DDevice9->GetRasterStatus(iSwapChain, pRasterStatus); -} - -HRESULT uMod_IDirect3DDevice9::SetDialogBoxMode(BOOL bEnableDialogs) -{ - return m_pIDirect3DDevice9->SetDialogBoxMode(bEnableDialogs); -} - -void uMod_IDirect3DDevice9::SetGammaRamp(UINT iSwapChain, DWORD Flags,CONST D3DGAMMARAMP* pRamp) -{ - return m_pIDirect3DDevice9->SetGammaRamp(iSwapChain, Flags, pRamp); -} - -void uMod_IDirect3DDevice9::GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP* pRamp) -{ - return m_pIDirect3DDevice9->GetGammaRamp(iSwapChain, pRamp); -} - -HRESULT uMod_IDirect3DDevice9::CreateTexture(UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle) -{ - //create real texture - Message("uMod_IDirect3DDevice9::CreateTexture()\n"); - const HRESULT ret = m_pIDirect3DDevice9->CreateTexture(Width, Height, Levels, Usage, Format, Pool, ppTexture, pSharedHandle); - if (ret != D3D_OK) { - return ret; - } - - const auto texture = new uMod_IDirect3DTexture9(ppTexture, this); - *ppTexture = texture; - - if (LastCreatedTexture != nullptr && uMod_Client != nullptr) //if a texture was loaded before, hopefully this texture contains now the data, so we can add it - { - uMod_Client->AddTexture(LastCreatedTexture); - } - LastCreatedTexture = texture; - return ret; -} - -HRESULT uMod_IDirect3DDevice9::CreateVolumeTexture(UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) -{ - //create real texture - Message("uMod_IDirect3DDevice9::CreateVolumeTexture()\n"); - const HRESULT ret = m_pIDirect3DDevice9->CreateVolumeTexture(Width, Height, Depth, Levels, Usage, Format, Pool, ppVolumeTexture, pSharedHandle); - if (ret != D3D_OK) { - return ret; - } - - //create fake texture - const auto texture = new uMod_IDirect3DVolumeTexture9(ppVolumeTexture, this); - *ppVolumeTexture = texture; - - if (LastCreatedVolumeTexture != nullptr && uMod_Client != nullptr) //if a texture was loaded before, hopefully this texture contains now the data, so we can add it - { - uMod_Client->AddTexture(LastCreatedVolumeTexture); - } - LastCreatedVolumeTexture = texture; - return ret; -} - -HRESULT uMod_IDirect3DDevice9::CreateCubeTexture(UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) -{ - //create real texture - Message("uMod_IDirect3DDevice9::CreateCubeTexture()\n"); - const HRESULT ret = m_pIDirect3DDevice9->CreateCubeTexture(EdgeLength, Levels, Usage, Format, Pool, ppCubeTexture, pSharedHandle); - if (ret != D3D_OK) { - return ret; - } - - //create fake texture - const auto texture = new uMod_IDirect3DCubeTexture9(ppCubeTexture, this); - *ppCubeTexture = texture; - - if (LastCreatedCubeTexture != nullptr && uMod_Client != nullptr) //if a texture was loaded before, hopefully this texture contains now the data, so we can add it - { - uMod_Client->AddTexture(LastCreatedCubeTexture); - } - LastCreatedCubeTexture = texture; - return ret; -} - -HRESULT uMod_IDirect3DDevice9::CreateVertexBuffer(UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle) -{ - return m_pIDirect3DDevice9->CreateVertexBuffer(Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle); -} - -HRESULT uMod_IDirect3DDevice9::CreateIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle) -{ - return m_pIDirect3DDevice9->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, pSharedHandle); -} - -HRESULT uMod_IDirect3DDevice9::CreateRenderTarget(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) -{ - return m_pIDirect3DDevice9->CreateRenderTarget(Width, Height, Format, MultiSample, MultisampleQuality, Lockable, ppSurface, pSharedHandle); -} - -HRESULT uMod_IDirect3DDevice9::CreateDepthStencilSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) -{ - return m_pIDirect3DDevice9->CreateDepthStencilSurface(Width, Height, Format, MultiSample, MultisampleQuality, Discard, ppSurface, pSharedHandle); -} - -HRESULT uMod_IDirect3DDevice9::UpdateSurface(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect, IDirect3DSurface9* pDestinationSurface,CONST POINT* pDestPoint) -{ - return m_pIDirect3DDevice9->UpdateSurface(pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint); -} - -HRESULT uMod_IDirect3DDevice9::UpdateTexture(IDirect3DBaseTexture9* pSourceTexture, IDirect3DBaseTexture9* pDestinationTexture) -{ - Message(PRE_MESSAGE "::UpdateTexture( %p, %p): %p\n", pSourceTexture, pDestinationTexture, this); - // we must pass the real texture objects - - - uMod_IDirect3DTexture9* pSource = nullptr; - uMod_IDirect3DVolumeTexture9* pSourceVolume = nullptr; - uMod_IDirect3DCubeTexture9* pSourceCube = nullptr; - IDirect3DBaseTexture9* cpy; - if (pSourceTexture != nullptr) { - const auto hash = pSource->GetHash(); - switch (pSourceTexture->QueryInterface(IID_IDirect3D9, (void**)&cpy)) { - case 0x01000000L: { - pSource = static_cast(pSourceTexture); - if (hash) { - if (hash != pSource->Hash) // this hash has changed !! - { - pSource->Hash = hash; - if (pSource->CrossRef_D3Dtex != nullptr) { - UnswitchTextures(pSource); - } - uMod_Client->LookUpToMod(pSource); - } - } - else if (pSource->CrossRef_D3Dtex != nullptr) { - UnswitchTextures(pSource); // we better unswitch - } - - // the source must be the original texture if not switched and the fake texture if it is switched - if (pSource->CrossRef_D3Dtex != nullptr) { - pSourceTexture = pSource->CrossRef_D3Dtex->m_D3Dtex; - } - else { - pSourceTexture = pSource->m_D3Dtex; - } - break; - } - case 0x01000001L: { - pSourceVolume = static_cast(pSourceTexture); - if (hash) { - if (hash != pSourceVolume->Hash) // this hash has changed !! - { - pSourceVolume->Hash = hash; - if (pSourceVolume->CrossRef_D3Dtex != nullptr) { - UnswitchTextures(pSourceVolume); - } - uMod_Client->LookUpToMod(pSourceVolume); - } - } - else if (pSourceVolume->CrossRef_D3Dtex != nullptr) { - UnswitchTextures(pSourceVolume); // we better unswitch - } - - // the source must be the original texture if not switched and the fake texture if it is switched - if (pSourceVolume->CrossRef_D3Dtex != nullptr) { - pSourceTexture = pSourceVolume->CrossRef_D3Dtex->m_D3Dtex; - } - else { - pSourceTexture = pSourceVolume->m_D3Dtex; - } - break; - } - case 0x01000002L: { - pSourceCube = static_cast(pSourceTexture); - if (hash) { - if (hash != pSourceCube->Hash) // this hash has changed !! - { - pSourceCube->Hash = hash; - if (pSourceCube->CrossRef_D3Dtex != nullptr) { - UnswitchTextures(pSourceCube); - } - uMod_Client->LookUpToMod(pSourceCube); - } - } - else if (pSourceCube->CrossRef_D3Dtex != nullptr) { - UnswitchTextures(pSourceCube); // we better unswitch - } - - // the source must be the original texture if not switched and the fake texture if it is switched - if (pSourceCube->CrossRef_D3Dtex != nullptr) { - pSourceTexture = pSourceCube->CrossRef_D3Dtex->m_D3Dtex; - } - else { - pSourceTexture = pSourceCube->m_D3Dtex; - } - break; - } - default: - break; // this is no fake texture and QueryInterface failed, because IDirect3DBaseTexture9 object cannot be a IDirect3D9 object ;) - } - } - - - if (pDestinationTexture != nullptr) { - switch (pSourceTexture->QueryInterface(IID_IDirect3D9, (void**)&cpy)) { - case 0x01000000L: { - const auto pDest = static_cast(pDestinationTexture); - - if (pSource != nullptr && pDest->Hash != pSource->Hash) { - pDest->Hash = pSource->Hash; // take over the hash - UnswitchTextures(pDest); - if (pSource->CrossRef_D3Dtex != nullptr) { - uMod_IDirect3DTexture9* cpy2 = pSource->CrossRef_D3Dtex; - UnswitchTextures(pSource); - SwitchTextures(cpy2, pDest); - } - } - if (pDest->CrossRef_D3Dtex != nullptr) { - pDestinationTexture = pDest->CrossRef_D3Dtex->m_D3Dtex; // make sure to copy into the original texture - } - else { - pDestinationTexture = pDest->m_D3Dtex; - } - break; - } - case 0x01000001L: { - const auto pDest = static_cast(pDestinationTexture); - - if (pSourceVolume != nullptr && pDest->Hash != pSourceVolume->Hash) { - pDest->Hash = pSourceVolume->Hash; // take over the hash - UnswitchTextures(pDest); - if (pSourceVolume->CrossRef_D3Dtex != nullptr) { - uMod_IDirect3DVolumeTexture9* cpy2 = pSourceVolume->CrossRef_D3Dtex; - UnswitchTextures(pSourceVolume); - SwitchTextures(cpy2, pDest); - } - } - if (pDest->CrossRef_D3Dtex != nullptr) { - pDestinationTexture = pDest->CrossRef_D3Dtex->m_D3Dtex; // make sure to copy into the original texture - } - else { - pDestinationTexture = pDest->m_D3Dtex; - } - break; - } - case 0x01000002L: { - auto pDest = static_cast(pDestinationTexture); - - if (pSourceCube != nullptr && pDest->Hash != pSourceCube->Hash) { - pDest->Hash = pSourceCube->Hash; // take over the hash - UnswitchTextures(pDest); - if (pSourceCube->CrossRef_D3Dtex != nullptr) { - uMod_IDirect3DCubeTexture9* cpy2 = pSourceCube->CrossRef_D3Dtex; - UnswitchTextures(pSourceCube); - SwitchTextures(cpy2, pDest); - } - } - if (pDest->CrossRef_D3Dtex != nullptr) { - pDestinationTexture = pDest->CrossRef_D3Dtex->m_D3Dtex; // make sure to copy into the original texture - } - else { - pDestinationTexture = pDest->m_D3Dtex; - } - break; - } - } - } - return m_pIDirect3DDevice9->UpdateTexture(pSourceTexture, pDestinationTexture); -} - -HRESULT uMod_IDirect3DDevice9::GetRenderTargetData(IDirect3DSurface9* pRenderTarget, IDirect3DSurface9* pDestSurface) -{ - return m_pIDirect3DDevice9->GetRenderTargetData(pRenderTarget, pDestSurface); -} - -HRESULT uMod_IDirect3DDevice9::GetFrontBufferData(UINT iSwapChain, IDirect3DSurface9* pDestSurface) -{ - return m_pIDirect3DDevice9->GetFrontBufferData(iSwapChain, pDestSurface); -} - -HRESULT uMod_IDirect3DDevice9::StretchRect(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) -{ - return m_pIDirect3DDevice9->StretchRect(pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter); -} - -HRESULT uMod_IDirect3DDevice9::ColorFill(IDirect3DSurface9* pSurface,CONST RECT* pRect, D3DCOLOR color) -{ - return m_pIDirect3DDevice9->ColorFill(pSurface, pRect, color); -} - -HRESULT uMod_IDirect3DDevice9::CreateOffscreenPlainSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) -{ - return m_pIDirect3DDevice9->CreateOffscreenPlainSurface(Width, Height, Format, Pool, ppSurface, pSharedHandle); -} - -HRESULT uMod_IDirect3DDevice9::SetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) -{ - { - IDirect3DSurface9* back_buffer; - NormalRendering = false; - for (int i = 0; !NormalRendering && i < BackBufferCount; i++) { - m_pIDirect3DDevice9->GetBackBuffer(0, i, D3DBACKBUFFER_TYPE_MONO, &back_buffer); - if (back_buffer == pRenderTarget) { - NormalRendering = true; - } - back_buffer->Release(); - } - } - return m_pIDirect3DDevice9->SetRenderTarget(RenderTargetIndex, pRenderTarget); -} - -HRESULT uMod_IDirect3DDevice9::GetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9** ppRenderTarget) -{ - return m_pIDirect3DDevice9->GetRenderTarget(RenderTargetIndex, ppRenderTarget); -} - -HRESULT uMod_IDirect3DDevice9::SetDepthStencilSurface(IDirect3DSurface9* pNewZStencil) -{ - return m_pIDirect3DDevice9->SetDepthStencilSurface(pNewZStencil); -} - -HRESULT uMod_IDirect3DDevice9::GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface) -{ - return m_pIDirect3DDevice9->GetDepthStencilSurface(ppZStencilSurface); -} - -HRESULT uMod_IDirect3DDevice9::BeginScene() -{ - if (LastCreatedTexture != nullptr) // add the last created texture - { - uMod_Client->AddTexture(LastCreatedTexture); - } - if (LastCreatedVolumeTexture != nullptr) // add the last created texture - { - uMod_Client->AddTexture(LastCreatedVolumeTexture); - } - if (LastCreatedCubeTexture != nullptr) // add the last created texture - { - uMod_Client->AddTexture(LastCreatedCubeTexture); - } - uMod_Client->MergeUpdate(); // merge an update, if present - - return m_pIDirect3DDevice9->BeginScene(); -} - -HRESULT uMod_IDirect3DDevice9::EndScene() -{ - return m_pIDirect3DDevice9->EndScene(); -} - -HRESULT uMod_IDirect3DDevice9::Clear(DWORD Count,CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) -{ - return m_pIDirect3DDevice9->Clear(Count, pRects, Flags, Color, Z, Stencil); -} - -HRESULT uMod_IDirect3DDevice9::SetTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) -{ - return m_pIDirect3DDevice9->SetTransform(State, pMatrix); -} - -HRESULT uMod_IDirect3DDevice9::GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) -{ - return m_pIDirect3DDevice9->GetTransform(State, pMatrix); -} - -HRESULT uMod_IDirect3DDevice9::MultiplyTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) -{ - return m_pIDirect3DDevice9->MultiplyTransform(State, pMatrix); -} - -HRESULT uMod_IDirect3DDevice9::SetViewport(CONST D3DVIEWPORT9* pViewport) -{ - return m_pIDirect3DDevice9->SetViewport(pViewport); -} - -HRESULT uMod_IDirect3DDevice9::GetViewport(D3DVIEWPORT9* pViewport) -{ - return m_pIDirect3DDevice9->GetViewport(pViewport); -} - -HRESULT uMod_IDirect3DDevice9::SetMaterial(CONST D3DMATERIAL9* pMaterial) -{ - return m_pIDirect3DDevice9->SetMaterial(pMaterial); -} - -HRESULT uMod_IDirect3DDevice9::GetMaterial(D3DMATERIAL9* pMaterial) -{ - return m_pIDirect3DDevice9->GetMaterial(pMaterial); -} - -HRESULT uMod_IDirect3DDevice9::SetLight(DWORD Index,CONST D3DLIGHT9* pLight) -{ - return m_pIDirect3DDevice9->SetLight(Index, pLight); -} - -HRESULT uMod_IDirect3DDevice9::GetLight(DWORD Index, D3DLIGHT9* pLight) -{ - return m_pIDirect3DDevice9->GetLight(Index, pLight); -} - -HRESULT uMod_IDirect3DDevice9::LightEnable(DWORD Index, BOOL Enable) -{ - return m_pIDirect3DDevice9->LightEnable(Index, Enable); -} - -HRESULT uMod_IDirect3DDevice9::GetLightEnable(DWORD Index, BOOL* pEnable) -{ - return m_pIDirect3DDevice9->GetLightEnable(Index, pEnable); -} - -HRESULT uMod_IDirect3DDevice9::SetClipPlane(DWORD Index,CONST float* pPlane) -{ - return m_pIDirect3DDevice9->SetClipPlane(Index, pPlane); -} - -HRESULT uMod_IDirect3DDevice9::GetClipPlane(DWORD Index, float* pPlane) -{ - return m_pIDirect3DDevice9->GetClipPlane(Index, pPlane); -} - -HRESULT uMod_IDirect3DDevice9::SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) -{ - return m_pIDirect3DDevice9->SetRenderState(State, Value); -} - -HRESULT uMod_IDirect3DDevice9::GetRenderState(D3DRENDERSTATETYPE State, DWORD* pValue) -{ - return m_pIDirect3DDevice9->GetRenderState(State, pValue); -} - -HRESULT uMod_IDirect3DDevice9::CreateStateBlock(D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9** ppSB) -{ - return m_pIDirect3DDevice9->CreateStateBlock(Type, ppSB); -} - -HRESULT uMod_IDirect3DDevice9::BeginStateBlock() -{ - return m_pIDirect3DDevice9->BeginStateBlock(); -} - -HRESULT uMod_IDirect3DDevice9::EndStateBlock(IDirect3DStateBlock9** ppSB) -{ - return m_pIDirect3DDevice9->EndStateBlock(ppSB); -} - -HRESULT uMod_IDirect3DDevice9::SetClipStatus(CONST D3DCLIPSTATUS9* pClipStatus) -{ - return m_pIDirect3DDevice9->SetClipStatus(pClipStatus); -} - -HRESULT uMod_IDirect3DDevice9::GetClipStatus(D3DCLIPSTATUS9* pClipStatus) -{ - return m_pIDirect3DDevice9->GetClipStatus(pClipStatus); -} - -HRESULT uMod_IDirect3DDevice9::GetTexture(DWORD Stage, IDirect3DBaseTexture9** ppTexture) -{ - return m_pIDirect3DDevice9->GetTexture(Stage, ppTexture); -} - -HRESULT uMod_IDirect3DDevice9::SetTexture(DWORD Stage, IDirect3DBaseTexture9* pTexture) -{ - // we must pass the real texture objects - // if (dev != this) this texture was not initialized through our device and is thus no fake texture object - - //IDirect3DDevice9 *dev = NULL; - IDirect3DBaseTexture9* cpy; - if (pTexture != nullptr) { - long int ret = pTexture->QueryInterface(IID_IDirect3D9, (void**)&cpy); - switch (ret) { - case 0x01000000L: - pTexture = static_cast(pTexture)->m_D3Dtex; - break; - case 0x01000001L: - pTexture = static_cast(pTexture)->m_D3Dtex; - break; - case 0x01000002L: - pTexture = static_cast(pTexture)->m_D3Dtex; - break; - default: - break; // this is no fake texture and QueryInterface failed, because IDirect3DBaseTexture9 object cannot be a IDirect3D9 object ;) - } - } - /* - if (pTexture != NULL && ((uMod_IDirect3DTexture9*)(pTexture))->GetDevice(&dev) == D3D_OK) - { - if(dev == this) pTexture = ((uMod_IDirect3DTexture9*)(pTexture))->m_D3Dtex; - } - */ - return m_pIDirect3DDevice9->SetTexture(Stage, pTexture); -} - -HRESULT uMod_IDirect3DDevice9::GetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) -{ - return m_pIDirect3DDevice9->GetTextureStageState(Stage, Type, pValue); -} - -HRESULT uMod_IDirect3DDevice9::SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) -{ - return m_pIDirect3DDevice9->SetTextureStageState(Stage, Type, Value); -} - -HRESULT uMod_IDirect3DDevice9::GetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) -{ - return m_pIDirect3DDevice9->GetSamplerState(Sampler, Type, pValue); -} - -HRESULT uMod_IDirect3DDevice9::SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) -{ - return m_pIDirect3DDevice9->SetSamplerState(Sampler, Type, Value); -} - -HRESULT uMod_IDirect3DDevice9::ValidateDevice(DWORD* pNumPasses) -{ - return m_pIDirect3DDevice9->ValidateDevice(pNumPasses); -} - -HRESULT uMod_IDirect3DDevice9::SetPaletteEntries(UINT PaletteNumber,CONST PALETTEENTRY* pEntries) -{ - return m_pIDirect3DDevice9->SetPaletteEntries(PaletteNumber, pEntries); -} - -HRESULT uMod_IDirect3DDevice9::GetPaletteEntries(UINT PaletteNumber, PALETTEENTRY* pEntries) -{ - return m_pIDirect3DDevice9->GetPaletteEntries(PaletteNumber, pEntries); -} - -HRESULT uMod_IDirect3DDevice9::SetCurrentTexturePalette(UINT PaletteNumber) -{ - return m_pIDirect3DDevice9->SetCurrentTexturePalette(PaletteNumber); -} - -HRESULT uMod_IDirect3DDevice9::GetCurrentTexturePalette(UINT* PaletteNumber) -{ - return m_pIDirect3DDevice9->GetCurrentTexturePalette(PaletteNumber); -} - -HRESULT uMod_IDirect3DDevice9::SetScissorRect(CONST RECT* pRect) -{ - return m_pIDirect3DDevice9->SetScissorRect(pRect); -} - -HRESULT uMod_IDirect3DDevice9::GetScissorRect(RECT* pRect) -{ - return m_pIDirect3DDevice9->GetScissorRect(pRect); -} - -HRESULT uMod_IDirect3DDevice9::SetSoftwareVertexProcessing(BOOL bSoftware) -{ - return m_pIDirect3DDevice9->SetSoftwareVertexProcessing(bSoftware); -} - -BOOL uMod_IDirect3DDevice9::GetSoftwareVertexProcessing() -{ - return m_pIDirect3DDevice9->GetSoftwareVertexProcessing(); -} - -HRESULT uMod_IDirect3DDevice9::SetNPatchMode(float nSegments) -{ - return m_pIDirect3DDevice9->SetNPatchMode(nSegments); -} - -float uMod_IDirect3DDevice9::GetNPatchMode() -{ - return m_pIDirect3DDevice9->GetNPatchMode(); -} - -HRESULT uMod_IDirect3DDevice9::DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) -{ - return m_pIDirect3DDevice9->DrawPrimitive(PrimitiveType, StartVertex, PrimitiveCount); -} - -HRESULT uMod_IDirect3DDevice9::DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) -{ - return m_pIDirect3DDevice9->DrawIndexedPrimitive(PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount); -} - -HRESULT uMod_IDirect3DDevice9::DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount,CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) -{ - return m_pIDirect3DDevice9->DrawPrimitiveUP(PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride); -} - -HRESULT uMod_IDirect3DDevice9::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, UINT PrimitiveCount,CONST void* pIndexData, D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData, - UINT VertexStreamZeroStride) -{ - return m_pIDirect3DDevice9->DrawIndexedPrimitiveUP(PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride); -} - -HRESULT uMod_IDirect3DDevice9::ProcessVertices(UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) -{ - return m_pIDirect3DDevice9->ProcessVertices(SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags); -} - -HRESULT uMod_IDirect3DDevice9::CreateVertexDeclaration(CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) -{ - return m_pIDirect3DDevice9->CreateVertexDeclaration(pVertexElements, ppDecl); -} - -HRESULT uMod_IDirect3DDevice9::SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl) -{ - return m_pIDirect3DDevice9->SetVertexDeclaration(pDecl); -} - -HRESULT uMod_IDirect3DDevice9::GetVertexDeclaration(IDirect3DVertexDeclaration9** ppDecl) -{ - return m_pIDirect3DDevice9->GetVertexDeclaration(ppDecl); -} - -HRESULT uMod_IDirect3DDevice9::SetFVF(DWORD FVF) -{ - return m_pIDirect3DDevice9->SetFVF(FVF); -} - -HRESULT uMod_IDirect3DDevice9::GetFVF(DWORD* pFVF) -{ - return m_pIDirect3DDevice9->GetFVF(pFVF); -} - -HRESULT uMod_IDirect3DDevice9::CreateVertexShader(CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader) -{ - return m_pIDirect3DDevice9->CreateVertexShader(pFunction, ppShader); -} - -HRESULT uMod_IDirect3DDevice9::SetVertexShader(IDirect3DVertexShader9* pShader) -{ - return m_pIDirect3DDevice9->SetVertexShader(pShader); -} - -HRESULT uMod_IDirect3DDevice9::GetVertexShader(IDirect3DVertexShader9** ppShader) -{ - return m_pIDirect3DDevice9->GetVertexShader(ppShader); -} - -HRESULT uMod_IDirect3DDevice9::SetVertexShaderConstantF(UINT StartRegister,CONST float* pConstantData, UINT Vector4fCount) -{ - return m_pIDirect3DDevice9->SetVertexShaderConstantF(StartRegister, pConstantData, Vector4fCount); -} - -HRESULT uMod_IDirect3DDevice9::GetVertexShaderConstantF(UINT StartRegister, float* pConstantData, UINT Vector4fCount) -{ - return m_pIDirect3DDevice9->GetVertexShaderConstantF(StartRegister, pConstantData, Vector4fCount); -} - -HRESULT uMod_IDirect3DDevice9::SetVertexShaderConstantI(UINT StartRegister,CONST int* pConstantData, UINT Vector4iCount) -{ - return m_pIDirect3DDevice9->SetVertexShaderConstantI(StartRegister, pConstantData, Vector4iCount); -} - -HRESULT uMod_IDirect3DDevice9::GetVertexShaderConstantI(UINT StartRegister, int* pConstantData, UINT Vector4iCount) -{ - return m_pIDirect3DDevice9->GetVertexShaderConstantI(StartRegister, pConstantData, Vector4iCount); -} - -HRESULT uMod_IDirect3DDevice9::SetVertexShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData, UINT BoolCount) -{ - return m_pIDirect3DDevice9->SetVertexShaderConstantB(StartRegister, pConstantData, BoolCount); -} - -HRESULT uMod_IDirect3DDevice9::GetVertexShaderConstantB(UINT StartRegister, BOOL* pConstantData, UINT BoolCount) -{ - return m_pIDirect3DDevice9->GetVertexShaderConstantB(StartRegister, pConstantData, BoolCount); -} - -HRESULT uMod_IDirect3DDevice9::SetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride) -{ - return m_pIDirect3DDevice9->SetStreamSource(StreamNumber, pStreamData, OffsetInBytes, Stride); -} - -HRESULT uMod_IDirect3DDevice9::GetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* OffsetInBytes, UINT* pStride) -{ - return m_pIDirect3DDevice9->GetStreamSource(StreamNumber, ppStreamData, OffsetInBytes, pStride); -} - -HRESULT uMod_IDirect3DDevice9::SetStreamSourceFreq(UINT StreamNumber, UINT Divider) -{ - return m_pIDirect3DDevice9->SetStreamSourceFreq(StreamNumber, Divider); -} - -HRESULT uMod_IDirect3DDevice9::GetStreamSourceFreq(UINT StreamNumber, UINT* Divider) -{ - return m_pIDirect3DDevice9->GetStreamSourceFreq(StreamNumber, Divider); -} - -HRESULT uMod_IDirect3DDevice9::SetIndices(IDirect3DIndexBuffer9* pIndexData) -{ - return m_pIDirect3DDevice9->SetIndices(pIndexData); -} - -HRESULT uMod_IDirect3DDevice9::GetIndices(IDirect3DIndexBuffer9** ppIndexData) -{ - return m_pIDirect3DDevice9->GetIndices(ppIndexData); -} - -HRESULT uMod_IDirect3DDevice9::CreatePixelShader(CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader) -{ - return m_pIDirect3DDevice9->CreatePixelShader(pFunction, ppShader); -} - -HRESULT uMod_IDirect3DDevice9::SetPixelShader(IDirect3DPixelShader9* pShader) -{ - return m_pIDirect3DDevice9->SetPixelShader(pShader); -} - -HRESULT uMod_IDirect3DDevice9::GetPixelShader(IDirect3DPixelShader9** ppShader) -{ - return m_pIDirect3DDevice9->GetPixelShader(ppShader); -} - -HRESULT uMod_IDirect3DDevice9::SetPixelShaderConstantF(UINT StartRegister,CONST float* pConstantData, UINT Vector4fCount) -{ - return m_pIDirect3DDevice9->SetPixelShaderConstantF(StartRegister, pConstantData, Vector4fCount); -} - -HRESULT uMod_IDirect3DDevice9::GetPixelShaderConstantF(UINT StartRegister, float* pConstantData, UINT Vector4fCount) -{ - return m_pIDirect3DDevice9->GetPixelShaderConstantF(StartRegister, pConstantData, Vector4fCount); -} - -HRESULT uMod_IDirect3DDevice9::SetPixelShaderConstantI(UINT StartRegister,CONST int* pConstantData, UINT Vector4iCount) -{ - return m_pIDirect3DDevice9->SetPixelShaderConstantI(StartRegister, pConstantData, Vector4iCount); -} - -HRESULT uMod_IDirect3DDevice9::GetPixelShaderConstantI(UINT StartRegister, int* pConstantData, UINT Vector4iCount) -{ - return m_pIDirect3DDevice9->GetPixelShaderConstantI(StartRegister, pConstantData, Vector4iCount); -} - -HRESULT uMod_IDirect3DDevice9::SetPixelShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData, UINT BoolCount) -{ - return m_pIDirect3DDevice9->SetPixelShaderConstantB(StartRegister, pConstantData, BoolCount); -} - -HRESULT uMod_IDirect3DDevice9::GetPixelShaderConstantB(UINT StartRegister, BOOL* pConstantData, UINT BoolCount) -{ - return m_pIDirect3DDevice9->GetPixelShaderConstantB(StartRegister, pConstantData, BoolCount); -} - -HRESULT uMod_IDirect3DDevice9::DrawRectPatch(UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) -{ - return m_pIDirect3DDevice9->DrawRectPatch(Handle, pNumSegs, pRectPatchInfo); -} - -HRESULT uMod_IDirect3DDevice9::DrawTriPatch(UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) -{ - return m_pIDirect3DDevice9->DrawTriPatch(Handle, pNumSegs, pTriPatchInfo); -} - -HRESULT uMod_IDirect3DDevice9::DeletePatch(UINT Handle) -{ - return m_pIDirect3DDevice9->DeletePatch(Handle); -} - -HRESULT uMod_IDirect3DDevice9::CreateQuery(D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) -{ - return m_pIDirect3DDevice9->CreateQuery(Type, ppQuery); -} diff --git a/source/uMod_IDirect3DDevice9Ex.cpp b/source/uMod_IDirect3DDevice9Ex.cpp deleted file mode 100644 index efe4429..0000000 --- a/source/uMod_IDirect3DDevice9Ex.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include "Main.h" - -#define uMod_IDirect3DDevice9 uMod_IDirect3DDevice9Ex -#define IDirect3DDevice9 IDirect3DDevice9Ex -#define m_pIDirect3DDevice9 m_pIDirect3DDevice9Ex - -#define RETURN_QueryInterface 0x01000001L -#define PRE_MESSAGE "uMod_IDirect3DDevice9Ex" - -// ReSharper disable once CppUnusedIncludeDirective -#include "uMod_IDirect3DDevice9.cpp" - - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::CheckDeviceState(HWND hWindow) -{ - return m_pIDirect3DDevice9Ex->CheckDeviceState(hWindow); -} - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::CheckResourceResidency(IDirect3DResource9** ppResourceArray, UINT32 NumResources) -{ - return m_pIDirect3DDevice9Ex->CheckResourceResidency(ppResourceArray, NumResources); -} - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::ComposeRects(IDirect3DSurface9* pSource, IDirect3DSurface9* pDestination, IDirect3DVertexBuffer9* pSrcRectDescriptors, UINT NumRects, IDirect3DVertexBuffer9* pDstRectDescriptors, D3DCOMPOSERECTSOP Operation, - INT XOffset, INT YOffset) -{ - return m_pIDirect3DDevice9Ex->ComposeRects(pSource, pDestination, pSrcRectDescriptors, NumRects, pDstRectDescriptors, Operation, XOffset, YOffset); -} - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::CreateDepthStencilSurfaceEx(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle, DWORD Usage) -{ - return m_pIDirect3DDevice9Ex->CreateDepthStencilSurfaceEx(Width, Height, Format, MultiSample, MultisampleQuality, Discard, ppSurface, pSharedHandle, Usage); -} - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::CreateOffscreenPlainSurfaceEx(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle, DWORD Usage) -{ - return m_pIDirect3DDevice9Ex->CreateOffscreenPlainSurfaceEx(Width, Height, Format, Pool, ppSurface, pSharedHandle, Usage); -} - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::CreateRenderTargetEx(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle, DWORD Usage) -{ - return m_pIDirect3DDevice9Ex->CreateRenderTargetEx(Width, Height, Format, MultiSample, MultisampleQuality, Lockable, ppSurface, pSharedHandle, Usage); -} - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::GetDisplayModeEx(UINT iSwapChain, D3DDISPLAYMODEEX* pMode, D3DDISPLAYROTATION* pRotation) -{ - return m_pIDirect3DDevice9Ex->GetDisplayModeEx(iSwapChain, pMode, pRotation); -} - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::GetGPUThreadPriority(INT* pPriority) -{ - return m_pIDirect3DDevice9Ex->GetGPUThreadPriority(pPriority); -} - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::GetMaximumFrameLatency(UINT* pMaxLatency) -{ - return m_pIDirect3DDevice9Ex->GetMaximumFrameLatency(pMaxLatency); -} - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::PresentEx(const RECT* pSourceRect, const RECT* pDestRect, HWND hDestWindowOverride, const RGNDATA* pDirtyRegion, DWORD dwFlags) -{ - return m_pIDirect3DDevice9Ex->PresentEx(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags); -} - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::ResetEx(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode) -{ - return m_pIDirect3DDevice9Ex->ResetEx(pPresentationParameters, pFullscreenDisplayMode); -} - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::SetConvolutionMonoKernel(UINT Width, UINT Height, float* RowWeights, float* ColumnWeights) -{ - return m_pIDirect3DDevice9Ex->SetConvolutionMonoKernel(Width, Height, RowWeights, ColumnWeights); -} - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::SetGPUThreadPriority(INT pPriority) -{ - return m_pIDirect3DDevice9Ex->SetGPUThreadPriority(pPriority); -} - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::SetMaximumFrameLatency(UINT pMaxLatency) -{ - return m_pIDirect3DDevice9Ex->SetMaximumFrameLatency(pMaxLatency); -} - -/* -HRESULT __stdcall uMod_IDirect3DDevice9Ex::TestCooperativeLevel() -{ - return(m_pIDirect3DDevice9Ex->TestCooperativeLevel(); -} -*/ - -HRESULT __stdcall uMod_IDirect3DDevice9Ex::WaitForVBlank(UINT SwapChainIndex) -{ - return m_pIDirect3DDevice9Ex->WaitForVBlank(SwapChainIndex); -} diff --git a/source/uMod_IDirect3DTexture9.cpp b/source/uMod_IDirect3DTexture9.cpp deleted file mode 100644 index 5bfa5af..0000000 --- a/source/uMod_IDirect3DTexture9.cpp +++ /dev/null @@ -1,348 +0,0 @@ -#include "Main.h" - -import ModfileLoader; -import TextureClient; -import TextureFunction; - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DTexture9::QueryInterface(REFIID riid, void** ppvObj) -{ - if (riid == IID_IDirect3D9) { - // This function should never be called with IID_IDirect3D9 by the game - // thus this call comes from our own dll to ask for the texture type - // 0x01000000L == uMod_IDirect3DTexture9 - // 0x01000001L == uMod_IDirect3DVolumeTexture9 - // 0x01000002L == uMod_IDirect3DCubeTexture9 - - *ppvObj = this; - return 0x01000000L; - } - HRESULT hRes; - if (CrossRef_D3Dtex != nullptr) { - hRes = CrossRef_D3Dtex->m_D3Dtex->QueryInterface(riid, ppvObj); - if (*ppvObj == CrossRef_D3Dtex->m_D3Dtex) { - *ppvObj = this; - } - } - else { - hRes = m_D3Dtex->QueryInterface(riid, ppvObj); - if (*ppvObj == m_D3Dtex) { - *ppvObj = this; - } - } - return hRes; -} - -//this function yields for the non switched texture object -ULONG APIENTRY uMod_IDirect3DTexture9::AddRef() -{ - if (FAKE) { - return 1; //bug, this case should never happen - } - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->AddRef(); - } - return m_D3Dtex->AddRef(); -} - -//this function yields for the non switched texture object -ULONG APIENTRY uMod_IDirect3DTexture9::Release() -{ - Message("uMod_IDirect3DTexture9::Release(): %p\n", this); - - void* cpy; - const long ret = m_D3Ddev->QueryInterface(IID_IDirect3DTexture9, &cpy); - - ULONG count; - if (FAKE) { - UnswitchTextures(this); - count = m_D3Dtex->Release(); //count must be zero, cause we don't call AddRef of fake_textures - } - else { - if (CrossRef_D3Dtex != nullptr) //if this texture is switched with a fake texture - { - uMod_IDirect3DTexture9* fake_texture = CrossRef_D3Dtex; - count = fake_texture->m_D3Dtex->Release(); //release the original texture - if (count == 0) //if texture is released we switch the textures back - { - UnswitchTextures(this); - fake_texture->Release(); // we release the fake texture - } - } - else { - count = m_D3Dtex->Release(); - } - } - - if (count == 0) //if this texture is released, we clean up - { - // if this texture is the LastCreatedTexture, the next time LastCreatedTexture would be added, - // the hash of a non existing texture would be calculated - if (ret == 0x01000000L) { - if (static_cast(m_D3Ddev)->GetLastCreatedTexture() == this) { - static_cast(m_D3Ddev)->SetLastCreatedTexture(nullptr); - } - else { - static_cast(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client - } - } - else { - if (static_cast(m_D3Ddev)->GetLastCreatedTexture() == this) { - static_cast(m_D3Ddev)->SetLastCreatedTexture(nullptr); - } - else { - static_cast(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client - } - } - - delete this; - } - - Message("uMod_IDirect3DTexture9::Release() end: %p\n", this); - return count; -} - -HRESULT APIENTRY uMod_IDirect3DTexture9::GetDevice(IDirect3DDevice9** ppDevice) -{ - *ppDevice = m_D3Ddev; - return D3D_OK; -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DTexture9::SetPrivateData(REFGUID refguid,CONST void* pData, DWORD SizeOfData, DWORD Flags) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->SetPrivateData(refguid, pData, SizeOfData, Flags); - } - return m_D3Dtex->SetPrivateData(refguid, pData, SizeOfData, Flags); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DTexture9::GetPrivateData(REFGUID refguid, void* pData, DWORD* pSizeOfData) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->GetPrivateData(refguid, pData, pSizeOfData); - } - return m_D3Dtex->GetPrivateData(refguid, pData, pSizeOfData); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DTexture9::FreePrivateData(REFGUID refguid) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->FreePrivateData(refguid); - } - return m_D3Dtex->FreePrivateData(refguid); -} - -DWORD APIENTRY uMod_IDirect3DTexture9::SetPriority(DWORD PriorityNew) -{ - return m_D3Dtex->SetPriority(PriorityNew); -} - -DWORD APIENTRY uMod_IDirect3DTexture9::GetPriority() -{ - return m_D3Dtex->GetPriority(); -} - -void APIENTRY uMod_IDirect3DTexture9::PreLoad() -{ - m_D3Dtex->PreLoad(); -} - -D3DRESOURCETYPE APIENTRY uMod_IDirect3DTexture9::GetType() -{ - return m_D3Dtex->GetType(); -} - -DWORD APIENTRY uMod_IDirect3DTexture9::SetLOD(DWORD LODNew) -{ - return m_D3Dtex->SetLOD(LODNew); -} - -DWORD APIENTRY uMod_IDirect3DTexture9::GetLOD() -{ - return m_D3Dtex->GetLOD(); -} - -DWORD APIENTRY uMod_IDirect3DTexture9::GetLevelCount() -{ - return m_D3Dtex->GetLevelCount(); -} - -HRESULT APIENTRY uMod_IDirect3DTexture9::SetAutoGenFilterType(D3DTEXTUREFILTERTYPE FilterType) -{ - return m_D3Dtex->SetAutoGenFilterType(FilterType); -} - -D3DTEXTUREFILTERTYPE APIENTRY uMod_IDirect3DTexture9::GetAutoGenFilterType() -{ - return m_D3Dtex->GetAutoGenFilterType(); -} - -void APIENTRY uMod_IDirect3DTexture9::GenerateMipSubLevels() -{ - m_D3Dtex->GenerateMipSubLevels(); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DTexture9::GetLevelDesc(UINT Level, D3DSURFACE_DESC* pDesc) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->GetLevelDesc(Level, pDesc); - } - return m_D3Dtex->GetLevelDesc(Level, pDesc); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DTexture9::GetSurfaceLevel(UINT Level, IDirect3DSurface9** ppSurfaceLevel) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->GetSurfaceLevel(Level, ppSurfaceLevel); - } - return m_D3Dtex->GetSurfaceLevel(Level, ppSurfaceLevel); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DTexture9::LockRect(UINT Level, D3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->LockRect(Level, pLockedRect, pRect, Flags); - } - return m_D3Dtex->LockRect(Level, pLockedRect, pRect, Flags); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DTexture9::UnlockRect(UINT Level) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->UnlockRect(Level); - } - return m_D3Dtex->UnlockRect(Level); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DTexture9::AddDirtyRect(CONST RECT* pDirtyRect) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->AddDirtyRect(pDirtyRect); - } - return m_D3Dtex->AddDirtyRect(pDirtyRect); -} - - -HashTuple uMod_IDirect3DTexture9::GetHash() const -{ - ASSERT(!FAKE); - IDirect3DTexture9* pTexture = m_D3Dtex; - if (CrossRef_D3Dtex != nullptr) { - pTexture = CrossRef_D3Dtex->m_D3Dtex; - } - - IDirect3DSurface9* pOffscreenSurface = nullptr; - //IDirect3DTexture9 *pOffscreenTexture = NULL; - IDirect3DSurface9* pResolvedSurface = nullptr; - D3DLOCKED_RECT d3dlr; - D3DSURFACE_DESC desc; - - if (pTexture->GetLevelDesc(0, &desc) != D3D_OK) //get the format and the size of the texture - { - Warning("uMod_IDirect3DTexture9::GetHash() Failed: GetLevelDesc \n"); - return {}; - } - - Message("uMod_IDirect3DTexture9::GetHash() (%d %d) %d\n", desc.Width, desc.Height, desc.Format); - - - if (desc.Pool == D3DPOOL_DEFAULT) //get the raw data of the texture - { - //Message("uMod_IDirect3DTexture9::GetHash() (D3DPOOL_DEFAULT)\n"); - - IDirect3DSurface9* pSurfaceLevel_orig = nullptr; - if (pTexture->GetSurfaceLevel(0, &pSurfaceLevel_orig) != D3D_OK) { - Warning("uMod_IDirect3DTexture9::GetHash() Failed: GetSurfaceLevel 1 (D3DPOOL_DEFAULT)\n"); - return {}; - } - - if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) { - //Message("uMod_IDirect3DTexture9::GetHash() MultiSampleType\n"); - if (D3D_OK != m_D3Ddev->CreateRenderTarget(desc.Width, desc.Height, desc.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pResolvedSurface, nullptr)) { - pSurfaceLevel_orig->Release(); - Warning("uMod_IDirect3DTexture9::GetHash() Failed: CreateRenderTarget (D3DPOOL_DEFAULT)\n"); - return {}; - } - if (D3D_OK != m_D3Ddev->StretchRect(pSurfaceLevel_orig, nullptr, pResolvedSurface, nullptr, D3DTEXF_NONE)) { - pSurfaceLevel_orig->Release(); - Warning("uMod_IDirect3DTexture9::GetHash() Failed: StretchRect (D3DPOOL_DEFAULT)\n"); - return {}; - } - - pSurfaceLevel_orig = pResolvedSurface; - } - - if (D3D_OK != m_D3Ddev->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pOffscreenSurface, nullptr)) { - pSurfaceLevel_orig->Release(); - if (pResolvedSurface != nullptr) { - pResolvedSurface->Release(); - } - Warning("uMod_IDirect3DTexture9::GetHash() Failed: CreateOffscreenPlainSurface (D3DPOOL_DEFAULT)\n"); - return {}; - } - - if (D3D_OK != m_D3Ddev->GetRenderTargetData(pSurfaceLevel_orig, pOffscreenSurface)) { - pSurfaceLevel_orig->Release(); - if (pResolvedSurface != nullptr) { - pResolvedSurface->Release(); - } - pOffscreenSurface->Release(); - Warning("uMod_IDirect3DTexture9::GetHash() Failed: GetRenderTargetData (D3DPOOL_DEFAULT)\n"); - return {}; - } - pSurfaceLevel_orig->Release(); - - if (pOffscreenSurface->LockRect(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) { - if (pResolvedSurface != nullptr) { - pResolvedSurface->Release(); - } - pOffscreenSurface->Release(); - Warning("uMod_IDirect3DTexture9::GetHash() Failed: LockRect (D3DPOOL_DEFAULT)\n"); - return {}; - } - } - else if (pTexture->LockRect(0, &d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) { - Warning("uMod_IDirect3DTexture9::GetHash() Failed: LockRect 1\n"); - if (pTexture->GetSurfaceLevel(0, &pResolvedSurface) != D3D_OK) { - Warning("uMod_IDirect3DTexture9::GetHash() Failed: GetSurfaceLevel\n"); - return {}; - } - if (pResolvedSurface->LockRect(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) { - pResolvedSurface->Release(); - Warning("uMod_IDirect3DTexture9::GetHash() Failed: LockRect 2\n"); - return {}; - } - } - - const int size = (TextureFunction::GetBitsFromFormat(desc.Format) * desc.Width * desc.Height) / 8; - const auto crc32 = TextureFunction::get_crc32(static_cast(d3dlr.pBits), size); - const auto crc64 = HashCheck::Use64BitCrc() ? TextureFunction::get_crc64(static_cast(d3dlr.pBits), size) : 0; - - // Only release surfaces after we're finished with d3dlr - if (pOffscreenSurface != nullptr) { - pOffscreenSurface->UnlockRect(); - pOffscreenSurface->Release(); - if (pResolvedSurface != nullptr) { - pResolvedSurface->Release(); - } - } - else if (pResolvedSurface != nullptr) { - pResolvedSurface->UnlockRect(); - pResolvedSurface->Release(); - } - else { - pTexture->UnlockRect(0); - } - - Message("uMod_IDirect3DTexture9::GetHash() crc32 %#lX (%d %d) %d = %d\n", crc32, desc.Width, desc.Height, desc.Format, size); - Message("uMod_IDirect3DTexture9::GetHash() crc64 %#llX (%d %d) %d = %d\n", crc64, desc.Width, desc.Height, desc.Format, size); - return {crc32, crc64}; -} diff --git a/source/uMod_IDirect3DVolumeTexture9.cpp b/source/uMod_IDirect3DVolumeTexture9.cpp deleted file mode 100644 index 8cfcf3c..0000000 --- a/source/uMod_IDirect3DVolumeTexture9.cpp +++ /dev/null @@ -1,280 +0,0 @@ -#include "Main.h" - -import ModfileLoader; -import TextureClient; -import TextureFunction; - -HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::QueryInterface(REFIID riid, void** ppvObj) -{ - if (riid == IID_IDirect3D9) { - // This function should never be called with IID_IDirect3D9 by the game - // thus this call comes from our own dll to ask for the texture type - // 0x01000000L == uMod_IDirect3DTexture9 - // 0x01000001L == uMod_IDirect3DVolumeTexture9 - // 0x01000002L == uMod_IDirect3DCubeTexture9 - - *ppvObj = this; - return 0x01000001L; - } - HRESULT hRes; - if (CrossRef_D3Dtex != nullptr) { - hRes = CrossRef_D3Dtex->m_D3Dtex->QueryInterface(riid, ppvObj); - if (*ppvObj == CrossRef_D3Dtex->m_D3Dtex) { - *ppvObj = this; - } - } - else { - hRes = m_D3Dtex->QueryInterface(riid, ppvObj); - if (*ppvObj == m_D3Dtex) { - *ppvObj = this; - } - } - return hRes; -} - -//this function yields for the non switched texture object -ULONG APIENTRY uMod_IDirect3DVolumeTexture9::AddRef() -{ - if (FAKE) { - return 1; //bug, this case should never happen - } - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->AddRef(); - } - return m_D3Dtex->AddRef(); -} - -//this function yields for the non switched texture object -ULONG APIENTRY uMod_IDirect3DVolumeTexture9::Release() -{ - Message("uMod_IDirect3DVolumeTexture9::Release(): %p\n", this); - - void* cpy; - const long ret = m_D3Ddev->QueryInterface(IID_IDirect3DTexture9, &cpy); - - ULONG count; - if (FAKE) { - UnswitchTextures(this); - count = m_D3Dtex->Release(); //count must be zero, cause we don't call AddRef of fake_textures - } - else { - if (CrossRef_D3Dtex != nullptr) //if this texture is switched with a fake texture - { - uMod_IDirect3DVolumeTexture9* fake_texture = CrossRef_D3Dtex; - count = fake_texture->m_D3Dtex->Release(); //release the original texture - if (count == 0) //if texture is released we switch the textures back - { - UnswitchTextures(this); - fake_texture->Release(); // we release the fake texture - } - } - else { - count = m_D3Dtex->Release(); - } - } - - if (count == 0) //if this texture is released, we clean up - { - // if this texture is the LastCreatedTexture, the next time LastCreatedTexture would be added, - // the hash of a non existing texture would be calculated - if (ret == 0x01000000L) { - if (static_cast(m_D3Ddev)->GetLastCreatedVolumeTexture() == this) { - static_cast(m_D3Ddev)->SetLastCreatedVolumeTexture(nullptr); - } - else { - static_cast(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client - } - } - else { - if (static_cast(m_D3Ddev)->GetLastCreatedVolumeTexture() == this) { - static_cast(m_D3Ddev)->SetLastCreatedVolumeTexture(nullptr); - } - else { - static_cast(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client - } - } - - delete this; - } - return count; -} - -HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::GetDevice(IDirect3DDevice9** ppDevice) -{ - *ppDevice = m_D3Ddev; - return D3D_OK; -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::SetPrivateData(REFGUID refguid,CONST void* pData, DWORD SizeOfData, DWORD Flags) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->SetPrivateData(refguid, pData, SizeOfData, Flags); - } - return m_D3Dtex->SetPrivateData(refguid, pData, SizeOfData, Flags); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::GetPrivateData(REFGUID refguid, void* pData, DWORD* pSizeOfData) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->GetPrivateData(refguid, pData, pSizeOfData); - } - return m_D3Dtex->GetPrivateData(refguid, pData, pSizeOfData); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::FreePrivateData(REFGUID refguid) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->FreePrivateData(refguid); - } - return m_D3Dtex->FreePrivateData(refguid); -} - -DWORD APIENTRY uMod_IDirect3DVolumeTexture9::SetPriority(DWORD PriorityNew) -{ - return m_D3Dtex->SetPriority(PriorityNew); -} - -DWORD APIENTRY uMod_IDirect3DVolumeTexture9::GetPriority() -{ - return m_D3Dtex->GetPriority(); -} - -void APIENTRY uMod_IDirect3DVolumeTexture9::PreLoad() -{ - m_D3Dtex->PreLoad(); -} - -D3DRESOURCETYPE APIENTRY uMod_IDirect3DVolumeTexture9::GetType() -{ - return m_D3Dtex->GetType(); -} - -DWORD APIENTRY uMod_IDirect3DVolumeTexture9::SetLOD(DWORD LODNew) -{ - return m_D3Dtex->SetLOD(LODNew); -} - -DWORD APIENTRY uMod_IDirect3DVolumeTexture9::GetLOD() -{ - return m_D3Dtex->GetLOD(); -} - -DWORD APIENTRY uMod_IDirect3DVolumeTexture9::GetLevelCount() -{ - return m_D3Dtex->GetLevelCount(); -} - -HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::SetAutoGenFilterType(D3DTEXTUREFILTERTYPE FilterType) -{ - return m_D3Dtex->SetAutoGenFilterType(FilterType); -} - -D3DTEXTUREFILTERTYPE APIENTRY uMod_IDirect3DVolumeTexture9::GetAutoGenFilterType() -{ - return m_D3Dtex->GetAutoGenFilterType(); -} - -void APIENTRY uMod_IDirect3DVolumeTexture9::GenerateMipSubLevels() -{ - m_D3Dtex->GenerateMipSubLevels(); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::AddDirtyBox(CONST D3DBOX* pDirtyBox) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->AddDirtyBox(pDirtyBox); - } - return m_D3Dtex->AddDirtyBox(pDirtyBox); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::GetLevelDesc(UINT Level, D3DVOLUME_DESC* pDesc) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->GetLevelDesc(Level, pDesc); - } - return m_D3Dtex->GetLevelDesc(Level, pDesc); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::GetVolumeLevel(UINT Level, IDirect3DVolume9** ppVolumeLevel) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->GetVolumeLevel(Level, ppVolumeLevel); - } - return m_D3Dtex->GetVolumeLevel(Level, ppVolumeLevel); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::LockBox(UINT Level, D3DLOCKED_BOX* pLockedVolume, CONST D3DBOX* pBox, DWORD Flags) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->LockBox(Level, pLockedVolume, pBox, Flags); - } - return m_D3Dtex->LockBox(Level, pLockedVolume, pBox, Flags); -} - -//this function yields for the non switched texture object -HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::UnlockBox(UINT Level) -{ - if (CrossRef_D3Dtex != nullptr) { - return CrossRef_D3Dtex->m_D3Dtex->UnlockBox(Level); - } - return m_D3Dtex->UnlockBox(Level); -} - -HashTuple uMod_IDirect3DVolumeTexture9::GetHash() const -{ - if (FAKE) { - return {}; - } - IDirect3DVolumeTexture9* pTexture = m_D3Dtex; - if (CrossRef_D3Dtex != nullptr) { - pTexture = CrossRef_D3Dtex->m_D3Dtex; - } - - IDirect3DVolume9* pResolvedSurface = nullptr; - D3DLOCKED_BOX d3dlr; - D3DVOLUME_DESC desc; - - if (pTexture->GetLevelDesc(0, &desc) != D3D_OK) //get the format and the size of the texture - { - Warning("uMod_IDirect3DVolumeTexture9::GetHash() Failed: GetLevelDesc \n"); - return {}; - } - - Message("uMod_IDirect3DVolumeTexture9::GetHash() (%d %d %d) %d\n", desc.Width, desc.Height, desc.Depth, desc.Format); - if (pTexture->LockBox(0, &d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) { - Warning("uMod_IDirect3DVolumeTexture9::GetHash() Failed: LockRect 1\n"); - if (pTexture->GetVolumeLevel(0, &pResolvedSurface) != D3D_OK) { - Warning("uMod_IDirect3DVolumeTexture9::GetHash() Failed: GetSurfaceLevel\n"); - return {}; - } - if (pResolvedSurface->LockBox(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) { - pResolvedSurface->Release(); - Warning("uMod_IDirect3DVolumeTexture9::GetHash() Failed: LockRect 2\n"); - return {}; - } - } - - const int size = (TextureFunction::GetBitsFromFormat(desc.Format) * desc.Width * desc.Height * desc.Depth) / 8; - const auto crc32 = TextureFunction::get_crc32(static_cast(d3dlr.pBits), size); - const auto crc64 = HashCheck::Use64BitCrc() ? TextureFunction::get_crc64(static_cast(d3dlr.pBits), size) : 0; - - // Only release surfaces after we're finished with d3dlr - if (pResolvedSurface != nullptr) { - pResolvedSurface->UnlockBox(); - pResolvedSurface->Release(); - } - else { - pTexture->UnlockBox(0); - } - - Message("uMod_IDirect3DVolumeTexture9::GetHash() crc32 %#lX (%d %d) %d = %d\n", crc32, desc.Width, desc.Height, desc.Format, size); - Message("uMod_IDirect3DVolumeTexture9::GetHash() crc64 %#llX (%d %d) %d = %d\n", crc64, desc.Width, desc.Height, desc.Format, size); - return {crc32, crc64}; -}