Replace D3D9 proxy wrappers with vtable hooks

This commit is contained in:
henderkes
2026-06-03 22:11:28 +00:00
committed by DubbleClick
parent 63110be15a
commit 17c7d5bdfc
32 changed files with 1191 additions and 3105 deletions
+560
View File
@@ -0,0 +1,560 @@
#include "Main.h"
#include "D3D9Hooks.h"
#include "MinHook.h"
#include <mutex>
#include <unordered_map>
#include <vector>
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<void***>(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<void*> g_hooked_targets;
// device -> owning TextureClient
std::mutex g_devices_mutex;
std::unordered_map<IDirect3DDevice9*, TextureClient*> 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 <typename TDetour, typename TOrig>
bool Hook(void* target, TDetour detour, TOrig* original)
{
return HookRaw(target, reinterpret_cast<void*>(detour), reinterpret_cast<void**>(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<void**>(&o_DeviceRelease));
Hook(vt[kDevice_CreateTexture], &h_CreateTexture, reinterpret_cast<void**>(&o_CreateTexture));
Hook(vt[kDevice_CreateVolumeTexture], &h_CreateVolumeTexture, reinterpret_cast<void**>(&o_CreateVolumeTexture));
Hook(vt[kDevice_CreateCubeTexture], &h_CreateCubeTexture, reinterpret_cast<void**>(&o_CreateCubeTexture));
Hook(vt[kDevice_UpdateTexture], &h_UpdateTexture, reinterpret_cast<void**>(&o_UpdateTexture));
Hook(vt[kDevice_BeginScene], &h_BeginScene, reinterpret_cast<void**>(&o_BeginScene));
Hook(vt[kDevice_GetTexture], &h_GetTexture, reinterpret_cast<void**>(&o_GetTexture));
Hook(vt[kDevice_SetTexture], &h_SetTexture, reinterpret_cast<void**>(&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<void**>(&o_Tex2DRelease)))
g_tex2d_release_installed = true;
break;
case TexType::Volume:
if (!g_volume_release_installed && Hook(vt[kResource_Release], &h_VolumeRelease, reinterpret_cast<void**>(&o_VolumeRelease)))
g_volume_release_installed = true;
break;
case TexType::Cube:
if (!g_cube_release_installed && Hook(vt[kResource_Release], &h_CubeRelease, reinterpret_cast<void**>(&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<IDirect3DBaseTexture9*>(*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<IDirect3DBaseTexture9*>(*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<IDirect3DBaseTexture9*>(*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<IDirect3DBaseTexture9*>(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<void**>(&o_CreateDevice));
if (is_ex) {
Hook(vt[kIDirect3D9Ex_CreateDeviceEx], &h_CreateDeviceEx, reinterpret_cast<void**>(&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<const char*>(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<IDirect3DTexture9*>(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<IDirect3DVolumeTexture9*>(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<IDirect3DCubeTexture9*>(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 {};
}
+5 -5
View File
@@ -6,10 +6,10 @@
#include <Main.h>
__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);
+38 -17
View File
@@ -1,6 +1,7 @@
#include "Main.h"
#include <Psapi.h>
#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<IDirect3D9Ex*>(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
}
-134
View File
@@ -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;
}
-48
View File
@@ -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);
}
-283
View File
@@ -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<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetLastCreatedCubeTexture() == this) {
static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->SetLastCreatedCubeTexture(nullptr);
}
else {
static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client
}
}
else {
if (static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->GetLastCreatedCubeTexture() == this) {
static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->SetLastCreatedCubeTexture(nullptr);
}
else {
static_cast<uMod_IDirect3DDevice9Ex*>(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<char*>(d3dlr.pBits), size);
const auto crc64 = HashCheck::Use64BitCrc() ? TextureFunction::get_crc64(static_cast<char*>(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};
}
-914
View File
@@ -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<int>(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<uMod_IDirect3DTexture9*>(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<uMod_IDirect3DVolumeTexture9*>(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<uMod_IDirect3DCubeTexture9*>(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<uMod_IDirect3DTexture9*>(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<uMod_IDirect3DVolumeTexture9*>(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<uMod_IDirect3DCubeTexture9*>(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<uMod_IDirect3DTexture9*>(pTexture)->m_D3Dtex;
break;
case 0x01000001L:
pTexture = static_cast<uMod_IDirect3DVolumeTexture9*>(pTexture)->m_D3Dtex;
break;
case 0x01000002L:
pTexture = static_cast<uMod_IDirect3DCubeTexture9*>(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);
}
-95
View File
@@ -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);
}
-348
View File
@@ -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<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetLastCreatedTexture() == this) {
static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->SetLastCreatedTexture(nullptr);
}
else {
static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client
}
}
else {
if (static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->GetLastCreatedTexture() == this) {
static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->SetLastCreatedTexture(nullptr);
}
else {
static_cast<uMod_IDirect3DDevice9Ex*>(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<char*>(d3dlr.pBits), size);
const auto crc64 = HashCheck::Use64BitCrc() ? TextureFunction::get_crc64(static_cast<char*>(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};
}
-280
View File
@@ -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<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetLastCreatedVolumeTexture() == this) {
static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->SetLastCreatedVolumeTexture(nullptr);
}
else {
static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client
}
}
else {
if (static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->GetLastCreatedVolumeTexture() == this) {
static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->SetLastCreatedVolumeTexture(nullptr);
}
else {
static_cast<uMod_IDirect3DDevice9Ex*>(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<char*>(d3dlr.pBits), size);
const auto crc64 = HashCheck::Use64BitCrc() ? TextureFunction::get_crc64(static_cast<char*>(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};
}