mirror of
https://github.com/gwdevhub/gMod.git
synced 2026-07-15 15:09:30 +00:00
Replace D3D9 proxy wrappers with vtable hooks
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
---
|
||||
Language: Cpp
|
||||
Standard: Latest
|
||||
|
||||
# Long, hand-wrapped declarations (vtable typedefs, D3D signatures) are kept as
|
||||
# written rather than reflowed to a column.
|
||||
ColumnLimit: 0
|
||||
|
||||
IndentWidth: 4
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
AccessModifierOffset: -4
|
||||
NamespaceIndentation: All
|
||||
IndentCaseLabels: true
|
||||
PointerAlignment: Left
|
||||
MaxEmptyLinesToKeep: 2
|
||||
Cpp11BracedListStyle: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
FixNamespaceComments: false
|
||||
|
||||
# Include order is load-bearing in the Windows headers; never reorder.
|
||||
SortIncludes: Never
|
||||
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterFunction: true
|
||||
AfterControlStatement: Never
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterStruct: false
|
||||
AfterEnum: false
|
||||
AfterUnion: false
|
||||
AfterNamespace: false
|
||||
AfterExternBlock: false
|
||||
BeforeElse: true
|
||||
BeforeCatch: true
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
@@ -0,0 +1,40 @@
|
||||
name: gMod Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
clang-format:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.head_ref || github.ref_name }}
|
||||
|
||||
# Pinned to the version the tree was formatted with so CI and local agree.
|
||||
- name: Install clang-format
|
||||
run: pipx install clang-format==22.1.5
|
||||
|
||||
- name: Apply clang-format
|
||||
run: clang-format -i header/*.h source/*.cpp modules/*.ixx TpfConvert/src/*.ixx
|
||||
|
||||
# Push / same-repo PRs: commit the fixes back. Fork PRs can't be pushed to,
|
||||
# so fail the check instead and let the contributor format.
|
||||
- name: Commit fixes
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: "ci: apply clang-format"
|
||||
- name: Verify formatting (fork PRs)
|
||||
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository
|
||||
run: git diff --exit-code
|
||||
@@ -13,7 +13,8 @@ export struct TexEntry {
|
||||
};
|
||||
|
||||
namespace {
|
||||
HashType GetCrcFromFilename(const std::string& filename) {
|
||||
HashType GetCrcFromFilename(const std::string& filename)
|
||||
{
|
||||
const static std::regex re(R"(0[xX][0-9a-fA-F]{4,16})", std::regex::optimize);
|
||||
std::smatch match;
|
||||
if (!std::regex_search(filename, match, re)) {
|
||||
@@ -45,8 +46,7 @@ export class ModfileLoader {
|
||||
0x74, 0x61, 0x67, 0x5B, 0x60, 0x70, 0x45, 0x74,
|
||||
0x5C, 0x22, 0x74, 0x5D, 0x6E, 0x6A, 0x73, 0x41,
|
||||
0x77, 0x6E, 0x46, 0x47, 0x77, 0x49, 0x0C, 0x4B,
|
||||
0x46, 0x6F
|
||||
};
|
||||
0x46, 0x6F};
|
||||
|
||||
public:
|
||||
ModfileLoader(const std::filesystem::path& fileName);
|
||||
@@ -54,7 +54,6 @@ public:
|
||||
std::vector<TexEntry> GetContents() const;
|
||||
|
||||
private:
|
||||
|
||||
std::vector<TexEntry> GetTpfContents() const;
|
||||
|
||||
std::vector<TexEntry> GetFileContents() const;
|
||||
@@ -85,7 +84,7 @@ std::vector<TexEntry> ModfileLoader::GetTpfContents() const
|
||||
const auto buffer = tpf_reader.ReadToEnd();
|
||||
const auto zip_archive = libzippp::ZipArchive::fromBuffer(buffer.data(), buffer.size(), false, TPF_PASSWORD);
|
||||
if (!zip_archive) {
|
||||
std::print(stderr, "Failed to open tpf file: {} - {} uint8_ts!\n", file_name.string(), buffer.size());
|
||||
std::print(stderr, "Failed to open tpf file: {} - {} uint8_ts!\n", file_name.string(), buffer.size());
|
||||
return {};
|
||||
}
|
||||
zip_archive->setErrorHandlerCallback(
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
|
||||
// in the other zip libraries, these had to be cut off, with libzip we need to zero them out
|
||||
// cutting them off makes the archive invalid
|
||||
//data.resize(last_zero);
|
||||
// data.resize(last_zero);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace {
|
||||
d3dpp.hDeviceWindow = GetDesktopWindow();
|
||||
|
||||
if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetDesktopWindow(),
|
||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice))) {
|
||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice))) {
|
||||
std::print(stderr, "Failed to create Direct3D9 device\n");
|
||||
pD3D->Release();
|
||||
return false;
|
||||
@@ -105,7 +105,7 @@ int main(int argc, char* argv[])
|
||||
const auto mod_path = modfile.path();
|
||||
const auto backup_file = backup_path / mod_path.filename();
|
||||
|
||||
if (std::filesystem::exists( backup_file)) {
|
||||
if (std::filesystem::exists(backup_file)) {
|
||||
std::print("Skipping previous TpfConvert output: {}\n", mod_path.filename().string());
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
// Hooks the IDirect3D9(Ex) CreateDevice slot on the real object returned by
|
||||
// Direct3DCreate9(Ex); `is_ex` also hooks CreateDeviceEx. Requires a prior
|
||||
// MH_Initialize() (done in dll_main).
|
||||
void InstallD3D9Hooks(IDirect3D9* d3d9, bool is_ex);
|
||||
|
||||
// Reverts every gMod hook, leaving the host process as it was. Safe if nothing
|
||||
// was hooked.
|
||||
void RemoveAllD3D9Hooks();
|
||||
|
||||
// Registers a device that already existed when gMod was injected, so the
|
||||
// CreateDevice hook never ran: hooks its vtable and stands up a TextureClient.
|
||||
// Textures created from here on are modded; pre-existing ones stay unknown.
|
||||
// Returns false if the device is null or already registered.
|
||||
bool RegisterExistingDevice(IDirect3DDevice9* device);
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d9.h>
|
||||
#include "Defines.h"
|
||||
|
||||
// Per-texture side-state, kept in lookups keyed by the real texture pointer (see
|
||||
// D3D9Hooks.h). Holding it out-of-band leaves the game's own objects untouched,
|
||||
// so reverting the vtable hooks fully detaches gMod.
|
||||
|
||||
enum class TexType {
|
||||
Tex2D,
|
||||
Volume,
|
||||
Cube,
|
||||
};
|
||||
|
||||
// State for one texture: an "original" the game created, or a "fake" we loaded
|
||||
// from a mod to stand in for one.
|
||||
struct TexState {
|
||||
IDirect3DBaseTexture9* real = nullptr;
|
||||
// An original points at the fake bound in its place (or nullptr); a fake
|
||||
// points back at the original it replaces.
|
||||
TexState* partner = nullptr;
|
||||
IDirect3DDevice9* device = nullptr;
|
||||
TextureFileStruct* reference = nullptr; // the modfile backing a fake
|
||||
HashTuple hash = {};
|
||||
TexType type = TexType::Tex2D;
|
||||
bool isFake = false;
|
||||
};
|
||||
|
||||
// Content hash (CRC32 + optional CRC64) of an original texture. Defined in
|
||||
// D3D9Hooks.cpp.
|
||||
HashTuple GetTextureHash(const TexState* state);
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
//using HashType = DWORD32;
|
||||
// using HashType = DWORD32;
|
||||
using HashType = DWORD64;
|
||||
|
||||
struct HashTuple {
|
||||
@@ -37,7 +37,7 @@ struct TextureFileStruct {
|
||||
inline void Message([[maybe_unused]] const char* format, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
//const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
// const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
//[[maybe_unused]] const auto success = SetConsoleTextAttribute(hConsole, 0); // white
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
@@ -49,7 +49,7 @@ inline void Message([[maybe_unused]] const char* format, ...)
|
||||
inline void Info([[maybe_unused]] const char* format, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
//const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
// const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
//[[maybe_unused]] const auto success = SetConsoleTextAttribute(hConsole, 0); // white
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
+8
-9
@@ -33,14 +33,14 @@
|
||||
|
||||
// define error states
|
||||
#define uMod_ERROR_FATAL 1u
|
||||
#define uMod_ERROR_MUTEX 1u<<1
|
||||
#define uMod_ERROR_PIPE 1u<<2
|
||||
#define uMod_ERROR_MEMORY 1u<<3
|
||||
#define uMod_ERROR_TEXTURE 1u<<4
|
||||
#define uMod_ERROR_MULTIPLE_IDirect3D9 1u<<5
|
||||
#define uMod_ERROR_MULTIPLE_IDirect3DDevice9 1u<<6
|
||||
#define uMod_ERROR_UPDATE 1u<<7
|
||||
#define uMod_ERROR_SERVER 1u<<8
|
||||
#define uMod_ERROR_MUTEX 1u << 1
|
||||
#define uMod_ERROR_PIPE 1u << 2
|
||||
#define uMod_ERROR_MEMORY 1u << 3
|
||||
#define uMod_ERROR_TEXTURE 1u << 4
|
||||
#define uMod_ERROR_MULTIPLE_IDirect3D9 1u << 5
|
||||
#define uMod_ERROR_MULTIPLE_IDirect3DDevice9 1u << 6
|
||||
#define uMod_ERROR_UPDATE 1u << 7
|
||||
#define uMod_ERROR_SERVER 1u << 8
|
||||
|
||||
__declspec(noreturn) void FatalAssert(
|
||||
const char* expr,
|
||||
@@ -49,4 +49,3 @@ __declspec(noreturn) void FatalAssert(
|
||||
const char* function);
|
||||
|
||||
#define ASSERT(expr) ((void)(!!(expr) || (FatalAssert(#expr, __FILE__, (unsigned)__LINE__, __FUNCTION__), 0)))
|
||||
|
||||
|
||||
+3
-10
@@ -16,17 +16,10 @@
|
||||
|
||||
#include "Defines.h"
|
||||
#include "Error.h"
|
||||
#include "Defines.h"
|
||||
|
||||
#include "uMod_IDirect3D9.h"
|
||||
#include "uMod_IDirect3D9Ex.h"
|
||||
|
||||
#include "uMod_IDirect3DDevice9.h"
|
||||
#include "uMod_IDirect3DDevice9Ex.h"
|
||||
|
||||
#include "uMod_IDirect3DCubeTexture9.h"
|
||||
#include "uMod_IDirect3DTexture9.h"
|
||||
#include "uMod_IDirect3DVolumeTexture9.h"
|
||||
// gMod no longer subclasses the D3D9 interfaces; it hooks their vtable slots and
|
||||
// keeps per-object side-state in lookups (see D3D9State.h / D3D9Hooks.h).
|
||||
#include "D3D9State.h"
|
||||
|
||||
#pragma warning(disable : 4477)
|
||||
|
||||
|
||||
+4
-4
@@ -2,9 +2,8 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace utils
|
||||
{
|
||||
template<typename T>
|
||||
namespace utils {
|
||||
template <typename T>
|
||||
void erase_first(std::vector<T>& vec, const T& elem)
|
||||
{
|
||||
const auto found = std::ranges::find(vec, elem);
|
||||
@@ -13,7 +12,8 @@ namespace utils
|
||||
}
|
||||
}
|
||||
|
||||
inline std::wstring utf8_to_wstring(const std::string& utf8str) {
|
||||
inline std::wstring utf8_to_wstring(const std::string& utf8str)
|
||||
{
|
||||
if (utf8str.empty()) return {};
|
||||
|
||||
// Calculate the number of wide characters needed for the conversion
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
class uMod_IDirect3D9 : public IDirect3D9 {
|
||||
public:
|
||||
uMod_IDirect3D9(IDirect3D9* pOriginal);
|
||||
virtual ~uMod_IDirect3D9();
|
||||
|
||||
// The original DX9 function definitions
|
||||
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObj) override;
|
||||
ULONG __stdcall AddRef() override;
|
||||
ULONG __stdcall Release() override;
|
||||
HRESULT __stdcall RegisterSoftwareDevice(void* pInitializeFunction) override;
|
||||
UINT __stdcall GetAdapterCount() override;
|
||||
HRESULT __stdcall GetAdapterIdentifier(UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) override;
|
||||
UINT __stdcall GetAdapterModeCount(UINT Adapter, D3DFORMAT Format) override;
|
||||
HRESULT __stdcall EnumAdapterModes(UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) override;
|
||||
HRESULT __stdcall GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE* pMode) override;
|
||||
HRESULT __stdcall CheckDeviceType(UINT iAdapter, D3DDEVTYPE DevType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed) override;
|
||||
HRESULT __stdcall CheckDeviceFormat(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) override;
|
||||
HRESULT __stdcall CheckDeviceMultiSampleType(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) override;
|
||||
HRESULT __stdcall CheckDepthStencilMatch(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) override;
|
||||
HRESULT __stdcall CheckDeviceFormatConversion(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) override;
|
||||
HRESULT __stdcall GetDeviceCaps(UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) override;
|
||||
HMONITOR __stdcall GetAdapterMonitor(UINT Adapter) override;
|
||||
HRESULT __stdcall CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface) override;
|
||||
|
||||
private:
|
||||
IDirect3D9* m_pIDirect3D9;
|
||||
};
|
||||
@@ -1,39 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
class uMod_IDirect3D9Ex : public IDirect3D9Ex {
|
||||
public:
|
||||
uMod_IDirect3D9Ex(IDirect3D9Ex* pOriginal);
|
||||
virtual ~uMod_IDirect3D9Ex();
|
||||
|
||||
// The original DX9 function definitions
|
||||
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObj) override;
|
||||
ULONG __stdcall AddRef() override;
|
||||
ULONG __stdcall Release() override;
|
||||
HRESULT __stdcall RegisterSoftwareDevice(void* pInitializeFunction) override;
|
||||
UINT __stdcall GetAdapterCount() override;
|
||||
HRESULT __stdcall GetAdapterIdentifier(UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier) override;
|
||||
UINT __stdcall GetAdapterModeCount(UINT Adapter, D3DFORMAT Format) override;
|
||||
HRESULT __stdcall EnumAdapterModes(UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) override;
|
||||
HRESULT __stdcall GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE* pMode) override;
|
||||
HRESULT __stdcall CheckDeviceType(UINT iAdapter, D3DDEVTYPE DevType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed) override;
|
||||
HRESULT __stdcall CheckDeviceFormat(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) override;
|
||||
HRESULT __stdcall CheckDeviceMultiSampleType(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) override;
|
||||
HRESULT __stdcall CheckDepthStencilMatch(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) override;
|
||||
HRESULT __stdcall CheckDeviceFormatConversion(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat) override;
|
||||
HRESULT __stdcall GetDeviceCaps(UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps) override;
|
||||
HMONITOR __stdcall GetAdapterMonitor(UINT Adapter) override;
|
||||
HRESULT __stdcall CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface) override;
|
||||
|
||||
HRESULT __stdcall CreateDeviceEx(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode,
|
||||
IDirect3DDevice9Ex** ppReturnedDeviceInterface) override;
|
||||
HRESULT __stdcall EnumAdapterModesEx(UINT Adapter, const D3DDISPLAYMODEFILTER* pFilter, UINT Mode, D3DDISPLAYMODEEX* pMode) override;
|
||||
HRESULT __stdcall GetAdapterDisplayModeEx(UINT Adapter, D3DDISPLAYMODEEX* pMode, D3DDISPLAYROTATION* pRotation) override;
|
||||
HRESULT __stdcall GetAdapterLUID(UINT Adapter, LUID* pLUID) override;
|
||||
UINT __stdcall GetAdapterModeCountEx(UINT Adapter, const D3DDISPLAYMODEFILTER* pFilter) override;
|
||||
|
||||
private:
|
||||
IDirect3D9Ex* m_pIDirect3D9Ex;
|
||||
};
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
interface uMod_IDirect3DCubeTexture9 : IDirect3DCubeTexture9 {
|
||||
uMod_IDirect3DCubeTexture9(IDirect3DCubeTexture9** ppTex, IDirect3DDevice9* pIDirect3DDevice9)
|
||||
: m_D3Dtex(*ppTex),
|
||||
m_D3Ddev(pIDirect3DDevice9)
|
||||
{}
|
||||
|
||||
virtual ~uMod_IDirect3DCubeTexture9() = default;
|
||||
|
||||
// callback interface
|
||||
IDirect3DCubeTexture9* m_D3Dtex = nullptr;
|
||||
uMod_IDirect3DCubeTexture9* CrossRef_D3Dtex = nullptr;
|
||||
IDirect3DDevice9* m_D3Ddev = nullptr;
|
||||
TextureFileStruct* Reference = nullptr;
|
||||
HashTuple Hash = {};
|
||||
bool FAKE = false;
|
||||
|
||||
// original interface
|
||||
STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj) override;
|
||||
STDMETHOD_(ULONG, AddRef)() override;
|
||||
STDMETHOD_(ULONG, Release)() override;
|
||||
STDMETHOD(GetDevice)(IDirect3DDevice9** ppDevice) override;
|
||||
STDMETHOD(SetPrivateData)(REFGUID refguid,CONST void* pData, DWORD SizeOfData, DWORD Flags) override;
|
||||
STDMETHOD(GetPrivateData)(REFGUID refguid, void* pData, DWORD* pSizeOfData) override;
|
||||
STDMETHOD(FreePrivateData)(REFGUID refguid) override;
|
||||
STDMETHOD_(DWORD, SetPriority)(DWORD PriorityNew) override;
|
||||
STDMETHOD_(DWORD, GetPriority)() override;
|
||||
STDMETHOD_(void, PreLoad)() override;
|
||||
STDMETHOD_(D3DRESOURCETYPE, GetType)() override;
|
||||
STDMETHOD_(DWORD, SetLOD)(DWORD LODNew) override;
|
||||
STDMETHOD_(DWORD, GetLOD)() override;
|
||||
STDMETHOD_(DWORD, GetLevelCount)() override;
|
||||
STDMETHOD(SetAutoGenFilterType)(D3DTEXTUREFILTERTYPE FilterType) override;
|
||||
STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)() override;
|
||||
STDMETHOD_(void, GenerateMipSubLevels)() override;
|
||||
|
||||
STDMETHOD(AddDirtyRect)(D3DCUBEMAP_FACES FaceType, CONST RECT* pDirtyRect) override;
|
||||
STDMETHOD(GetLevelDesc)(UINT Level, D3DSURFACE_DESC* pDesc) override;
|
||||
STDMETHOD(GetCubeMapSurface)(D3DCUBEMAP_FACES FaceType, UINT Level, IDirect3DSurface9** ppCubeMapSurface) override;
|
||||
STDMETHOD(LockRect)(D3DCUBEMAP_FACES FaceType, UINT Level, D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect, DWORD Flags) override;
|
||||
STDMETHOD(UnlockRect)(D3DCUBEMAP_FACES FaceType, UINT Level) override;
|
||||
|
||||
|
||||
[[nodiscard]] HashTuple GetHash() const;
|
||||
};
|
||||
@@ -1,173 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d9.h>
|
||||
#include "uMod_IDirect3DTexture9.h"
|
||||
#include "uMod_IDirect3DVolumeTexture9.h"
|
||||
#include "uMod_IDirect3DCubeTexture9.h"
|
||||
|
||||
class TextureClient;
|
||||
|
||||
class uMod_IDirect3DDevice9 : public IDirect3DDevice9 {
|
||||
public:
|
||||
uMod_IDirect3DDevice9(IDirect3DDevice9* pOriginal, int back_buffer_count);
|
||||
virtual ~uMod_IDirect3DDevice9();
|
||||
|
||||
// START: The original DX9 function definitions
|
||||
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObj) override;
|
||||
ULONG __stdcall AddRef() override;
|
||||
ULONG __stdcall Release() override;
|
||||
HRESULT __stdcall TestCooperativeLevel() override;
|
||||
UINT __stdcall GetAvailableTextureMem() override;
|
||||
HRESULT __stdcall EvictManagedResources() override;
|
||||
HRESULT __stdcall GetDirect3D(IDirect3D9** ppD3D9) override;
|
||||
HRESULT __stdcall GetDeviceCaps(D3DCAPS9* pCaps) override;
|
||||
HRESULT __stdcall GetDisplayMode(UINT iSwapChain, D3DDISPLAYMODE* pMode) override;
|
||||
HRESULT __stdcall GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS* pParameters) override;
|
||||
HRESULT __stdcall SetCursorProperties(UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap) override;
|
||||
void __stdcall SetCursorPosition(int X, int Y, DWORD Flags) override;
|
||||
BOOL __stdcall ShowCursor(BOOL bShow) override;
|
||||
HRESULT __stdcall CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain) override;
|
||||
HRESULT __stdcall GetSwapChain(UINT iSwapChain, IDirect3DSwapChain9** pSwapChain) override;
|
||||
UINT __stdcall GetNumberOfSwapChains() override;
|
||||
HRESULT __stdcall Reset(D3DPRESENT_PARAMETERS* pPresentationParameters) override;
|
||||
HRESULT __stdcall Present(CONST RECT* pSourceRect,CONST RECT* pDestRect, HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) override;
|
||||
HRESULT __stdcall GetBackBuffer(UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) override;
|
||||
HRESULT __stdcall GetRasterStatus(UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) override;
|
||||
HRESULT __stdcall SetDialogBoxMode(BOOL bEnableDialogs) override;
|
||||
void __stdcall SetGammaRamp(UINT iSwapChain, DWORD Flags,CONST D3DGAMMARAMP* pRamp) override;
|
||||
void __stdcall GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP* pRamp) override;
|
||||
HRESULT __stdcall CreateTexture(UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall CreateVolumeTexture(UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall CreateCubeTexture(UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall CreateVertexBuffer(UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall CreateIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall CreateRenderTarget(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall CreateDepthStencilSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall UpdateSurface(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect, IDirect3DSurface9* pDestinationSurface,CONST POINT* pDestPoint) override;
|
||||
HRESULT __stdcall UpdateTexture(IDirect3DBaseTexture9* pSourceTexture, IDirect3DBaseTexture9* pDestinationTexture) override;
|
||||
HRESULT __stdcall GetRenderTargetData(IDirect3DSurface9* pRenderTarget, IDirect3DSurface9* pDestSurface) override;
|
||||
HRESULT __stdcall GetFrontBufferData(UINT iSwapChain, IDirect3DSurface9* pDestSurface) override;
|
||||
HRESULT __stdcall StretchRect(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) override;
|
||||
HRESULT __stdcall ColorFill(IDirect3DSurface9* pSurface,CONST RECT* pRect, D3DCOLOR color) override;
|
||||
HRESULT __stdcall CreateOffscreenPlainSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall SetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) override;
|
||||
HRESULT __stdcall GetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9** ppRenderTarget) override;
|
||||
HRESULT __stdcall SetDepthStencilSurface(IDirect3DSurface9* pNewZStencil) override;
|
||||
HRESULT __stdcall GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface) override;
|
||||
HRESULT __stdcall BeginScene() override;
|
||||
HRESULT __stdcall EndScene() override;
|
||||
HRESULT __stdcall Clear(DWORD Count,CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) override;
|
||||
HRESULT __stdcall SetTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) override;
|
||||
HRESULT __stdcall GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) override;
|
||||
HRESULT __stdcall MultiplyTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) override;
|
||||
HRESULT __stdcall SetViewport(CONST D3DVIEWPORT9* pViewport) override;
|
||||
HRESULT __stdcall GetViewport(D3DVIEWPORT9* pViewport) override;
|
||||
HRESULT __stdcall SetMaterial(CONST D3DMATERIAL9* pMaterial) override;
|
||||
HRESULT __stdcall GetMaterial(D3DMATERIAL9* pMaterial) override;
|
||||
HRESULT __stdcall SetLight(DWORD Index,CONST D3DLIGHT9* pLight) override;
|
||||
HRESULT __stdcall GetLight(DWORD Index, D3DLIGHT9* pLight) override;
|
||||
HRESULT __stdcall LightEnable(DWORD Index, BOOL Enable) override;
|
||||
HRESULT __stdcall GetLightEnable(DWORD Index, BOOL* pEnable) override;
|
||||
HRESULT __stdcall SetClipPlane(DWORD Index,CONST float* pPlane) override;
|
||||
HRESULT __stdcall GetClipPlane(DWORD Index, float* pPlane) override;
|
||||
HRESULT __stdcall SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) override;
|
||||
HRESULT __stdcall GetRenderState(D3DRENDERSTATETYPE State, DWORD* pValue) override;
|
||||
HRESULT __stdcall CreateStateBlock(D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9** ppSB) override;
|
||||
HRESULT __stdcall BeginStateBlock() override;
|
||||
HRESULT __stdcall EndStateBlock(IDirect3DStateBlock9** ppSB) override;
|
||||
HRESULT __stdcall SetClipStatus(CONST D3DCLIPSTATUS9* pClipStatus) override;
|
||||
HRESULT __stdcall GetClipStatus(D3DCLIPSTATUS9* pClipStatus) override;
|
||||
HRESULT __stdcall GetTexture(DWORD Stage, IDirect3DBaseTexture9** ppTexture) override;
|
||||
HRESULT __stdcall SetTexture(DWORD Stage, IDirect3DBaseTexture9* pTexture) override;
|
||||
HRESULT __stdcall GetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) override;
|
||||
HRESULT __stdcall SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) override;
|
||||
HRESULT __stdcall GetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) override;
|
||||
HRESULT __stdcall SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) override;
|
||||
HRESULT __stdcall ValidateDevice(DWORD* pNumPasses) override;
|
||||
HRESULT __stdcall SetPaletteEntries(UINT PaletteNumber,CONST PALETTEENTRY* pEntries) override;
|
||||
HRESULT __stdcall GetPaletteEntries(UINT PaletteNumber, PALETTEENTRY* pEntries) override;
|
||||
HRESULT __stdcall SetCurrentTexturePalette(UINT PaletteNumber) override;
|
||||
HRESULT __stdcall GetCurrentTexturePalette(UINT* PaletteNumber) override;
|
||||
HRESULT __stdcall SetScissorRect(CONST RECT* pRect) override;
|
||||
HRESULT __stdcall GetScissorRect(RECT* pRect) override;
|
||||
HRESULT __stdcall SetSoftwareVertexProcessing(BOOL bSoftware) override;
|
||||
BOOL __stdcall GetSoftwareVertexProcessing() override;
|
||||
HRESULT __stdcall SetNPatchMode(float nSegments) override;
|
||||
float __stdcall GetNPatchMode() override;
|
||||
HRESULT __stdcall DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) override;
|
||||
HRESULT __stdcall DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) override;
|
||||
HRESULT __stdcall DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount,CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) override;
|
||||
HRESULT __stdcall DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, UINT PrimitiveCount,CONST void* pIndexData, D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
|
||||
UINT VertexStreamZeroStride) override;
|
||||
HRESULT __stdcall ProcessVertices(UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) override;
|
||||
HRESULT __stdcall CreateVertexDeclaration(CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) override;
|
||||
HRESULT __stdcall SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl) override;
|
||||
HRESULT __stdcall GetVertexDeclaration(IDirect3DVertexDeclaration9** ppDecl) override;
|
||||
HRESULT __stdcall SetFVF(DWORD FVF) override;
|
||||
HRESULT __stdcall GetFVF(DWORD* pFVF) override;
|
||||
HRESULT __stdcall CreateVertexShader(CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader) override;
|
||||
HRESULT __stdcall SetVertexShader(IDirect3DVertexShader9* pShader) override;
|
||||
HRESULT __stdcall GetVertexShader(IDirect3DVertexShader9** ppShader) override;
|
||||
HRESULT __stdcall SetVertexShaderConstantF(UINT StartRegister,CONST float* pConstantData, UINT Vector4fCount) override;
|
||||
HRESULT __stdcall GetVertexShaderConstantF(UINT StartRegister, float* pConstantData, UINT Vector4fCount) override;
|
||||
HRESULT __stdcall SetVertexShaderConstantI(UINT StartRegister,CONST int* pConstantData, UINT Vector4iCount) override;
|
||||
HRESULT __stdcall GetVertexShaderConstantI(UINT StartRegister, int* pConstantData, UINT Vector4iCount) override;
|
||||
HRESULT __stdcall SetVertexShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData, UINT BoolCount) override;
|
||||
HRESULT __stdcall GetVertexShaderConstantB(UINT StartRegister, BOOL* pConstantData, UINT BoolCount) override;
|
||||
HRESULT __stdcall SetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride) override;
|
||||
HRESULT __stdcall GetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* OffsetInBytes, UINT* pStride) override;
|
||||
HRESULT __stdcall SetStreamSourceFreq(UINT StreamNumber, UINT Divider) override;
|
||||
HRESULT __stdcall GetStreamSourceFreq(UINT StreamNumber, UINT* Divider) override;
|
||||
HRESULT __stdcall SetIndices(IDirect3DIndexBuffer9* pIndexData) override;
|
||||
HRESULT __stdcall GetIndices(IDirect3DIndexBuffer9** ppIndexData) override;
|
||||
HRESULT __stdcall CreatePixelShader(CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader) override;
|
||||
HRESULT __stdcall SetPixelShader(IDirect3DPixelShader9* pShader) override;
|
||||
HRESULT __stdcall GetPixelShader(IDirect3DPixelShader9** ppShader) override;
|
||||
HRESULT __stdcall SetPixelShaderConstantF(UINT StartRegister,CONST float* pConstantData, UINT Vector4fCount) override;
|
||||
HRESULT __stdcall GetPixelShaderConstantF(UINT StartRegister, float* pConstantData, UINT Vector4fCount) override;
|
||||
HRESULT __stdcall SetPixelShaderConstantI(UINT StartRegister,CONST int* pConstantData, UINT Vector4iCount) override;
|
||||
HRESULT __stdcall GetPixelShaderConstantI(UINT StartRegister, int* pConstantData, UINT Vector4iCount) override;
|
||||
HRESULT __stdcall SetPixelShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData, UINT BoolCount) override;
|
||||
HRESULT __stdcall GetPixelShaderConstantB(UINT StartRegister, BOOL* pConstantData, UINT BoolCount) override;
|
||||
HRESULT __stdcall DrawRectPatch(UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) override;
|
||||
HRESULT __stdcall DrawTriPatch(UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) override;
|
||||
HRESULT __stdcall DeletePatch(UINT Handle) override;
|
||||
HRESULT __stdcall CreateQuery(D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) override;
|
||||
// END: The original DX9 function definitions
|
||||
|
||||
TextureClient* GetuMod_Client() { return uMod_Client; }
|
||||
|
||||
uMod_IDirect3DTexture9* GetLastCreatedTexture() { return LastCreatedTexture; }
|
||||
|
||||
void SetLastCreatedTexture(uMod_IDirect3DTexture9* pTexture)
|
||||
{
|
||||
LastCreatedTexture = pTexture;
|
||||
}
|
||||
|
||||
uMod_IDirect3DVolumeTexture9* GetLastCreatedVolumeTexture() { return LastCreatedVolumeTexture; }
|
||||
|
||||
void SetLastCreatedVolumeTexture(uMod_IDirect3DVolumeTexture9* pTexture)
|
||||
{
|
||||
LastCreatedVolumeTexture = pTexture;
|
||||
}
|
||||
|
||||
uMod_IDirect3DCubeTexture9* GetLastCreatedCubeTexture() { return LastCreatedCubeTexture; }
|
||||
|
||||
void SetLastCreatedCubeTexture(uMod_IDirect3DCubeTexture9* pTexture)
|
||||
{
|
||||
LastCreatedCubeTexture = pTexture;
|
||||
}
|
||||
|
||||
private:
|
||||
IDirect3DDevice9* m_pIDirect3DDevice9 = nullptr;
|
||||
|
||||
int BackBufferCount;
|
||||
bool NormalRendering = true;
|
||||
int uMod_Reference = 1;
|
||||
|
||||
uMod_IDirect3DTexture9* LastCreatedTexture = nullptr;
|
||||
uMod_IDirect3DVolumeTexture9* LastCreatedVolumeTexture = nullptr;
|
||||
uMod_IDirect3DCubeTexture9* LastCreatedCubeTexture = nullptr;
|
||||
|
||||
TextureClient* uMod_Client;
|
||||
};
|
||||
@@ -1,196 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d9.h>
|
||||
#include "uMod_IDirect3DTexture9.h"
|
||||
#include "uMod_IDirect3DVolumeTexture9.h"
|
||||
#include "uMod_IDirect3DCubeTexture9.h"
|
||||
|
||||
class TextureClient;
|
||||
|
||||
class uMod_IDirect3DDevice9Ex : public IDirect3DDevice9Ex {
|
||||
public:
|
||||
uMod_IDirect3DDevice9Ex(IDirect3DDevice9Ex* pOriginal, int back_buffer_count);
|
||||
virtual ~uMod_IDirect3DDevice9Ex();
|
||||
|
||||
// START: The original DX9 function definitions
|
||||
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObj) override;
|
||||
ULONG __stdcall AddRef() override;
|
||||
ULONG __stdcall Release() override;
|
||||
HRESULT __stdcall TestCooperativeLevel() override;
|
||||
UINT __stdcall GetAvailableTextureMem() override;
|
||||
HRESULT __stdcall EvictManagedResources() override;
|
||||
HRESULT __stdcall GetDirect3D(IDirect3D9** ppD3D9) override;
|
||||
HRESULT __stdcall GetDeviceCaps(D3DCAPS9* pCaps) override;
|
||||
HRESULT __stdcall GetDisplayMode(UINT iSwapChain, D3DDISPLAYMODE* pMode) override;
|
||||
HRESULT __stdcall GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS* pParameters) override;
|
||||
HRESULT __stdcall SetCursorProperties(UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9* pCursorBitmap) override;
|
||||
void __stdcall SetCursorPosition(int X, int Y, DWORD Flags) override;
|
||||
BOOL __stdcall ShowCursor(BOOL bShow) override;
|
||||
HRESULT __stdcall CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain9** pSwapChain) override;
|
||||
HRESULT __stdcall GetSwapChain(UINT iSwapChain, IDirect3DSwapChain9** pSwapChain) override;
|
||||
UINT __stdcall GetNumberOfSwapChains() override;
|
||||
HRESULT __stdcall Reset(D3DPRESENT_PARAMETERS* pPresentationParameters) override;
|
||||
HRESULT __stdcall Present(CONST RECT* pSourceRect,CONST RECT* pDestRect, HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) override;
|
||||
HRESULT __stdcall GetBackBuffer(UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) override;
|
||||
HRESULT __stdcall GetRasterStatus(UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) override;
|
||||
HRESULT __stdcall SetDialogBoxMode(BOOL bEnableDialogs) override;
|
||||
void __stdcall SetGammaRamp(UINT iSwapChain, DWORD Flags,CONST D3DGAMMARAMP* pRamp) override;
|
||||
void __stdcall GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP* pRamp) override;
|
||||
HRESULT __stdcall CreateTexture(UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall CreateVolumeTexture(UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9** ppVolumeTexture, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall CreateCubeTexture(UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9** ppCubeTexture, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall CreateVertexBuffer(UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall CreateIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall CreateRenderTarget(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall CreateDepthStencilSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall UpdateSurface(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect, IDirect3DSurface9* pDestinationSurface,CONST POINT* pDestPoint) override;
|
||||
HRESULT __stdcall UpdateTexture(IDirect3DBaseTexture9* pSourceTexture, IDirect3DBaseTexture9* pDestinationTexture) override;
|
||||
HRESULT __stdcall GetRenderTargetData(IDirect3DSurface9* pRenderTarget, IDirect3DSurface9* pDestSurface) override;
|
||||
HRESULT __stdcall GetFrontBufferData(UINT iSwapChain, IDirect3DSurface9* pDestSurface) override;
|
||||
HRESULT __stdcall StretchRect(IDirect3DSurface9* pSourceSurface,CONST RECT* pSourceRect, IDirect3DSurface9* pDestSurface,CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) override;
|
||||
HRESULT __stdcall ColorFill(IDirect3DSurface9* pSurface,CONST RECT* pRect, D3DCOLOR color) override;
|
||||
HRESULT __stdcall CreateOffscreenPlainSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) override;
|
||||
HRESULT __stdcall SetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9* pRenderTarget) override;
|
||||
HRESULT __stdcall GetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9** ppRenderTarget) override;
|
||||
HRESULT __stdcall SetDepthStencilSurface(IDirect3DSurface9* pNewZStencil) override;
|
||||
HRESULT __stdcall GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface) override;
|
||||
HRESULT __stdcall BeginScene() override;
|
||||
HRESULT __stdcall EndScene() override;
|
||||
HRESULT __stdcall Clear(DWORD Count,CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) override;
|
||||
HRESULT __stdcall SetTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) override;
|
||||
HRESULT __stdcall GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) override;
|
||||
HRESULT __stdcall MultiplyTransform(D3DTRANSFORMSTATETYPE State,CONST D3DMATRIX* pMatrix) override;
|
||||
HRESULT __stdcall SetViewport(CONST D3DVIEWPORT9* pViewport) override;
|
||||
HRESULT __stdcall GetViewport(D3DVIEWPORT9* pViewport) override;
|
||||
HRESULT __stdcall SetMaterial(CONST D3DMATERIAL9* pMaterial) override;
|
||||
HRESULT __stdcall GetMaterial(D3DMATERIAL9* pMaterial) override;
|
||||
HRESULT __stdcall SetLight(DWORD Index,CONST D3DLIGHT9* pLight) override;
|
||||
HRESULT __stdcall GetLight(DWORD Index, D3DLIGHT9* pLight) override;
|
||||
HRESULT __stdcall LightEnable(DWORD Index, BOOL Enable) override;
|
||||
HRESULT __stdcall GetLightEnable(DWORD Index, BOOL* pEnable) override;
|
||||
HRESULT __stdcall SetClipPlane(DWORD Index,CONST float* pPlane) override;
|
||||
HRESULT __stdcall GetClipPlane(DWORD Index, float* pPlane) override;
|
||||
HRESULT __stdcall SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) override;
|
||||
HRESULT __stdcall GetRenderState(D3DRENDERSTATETYPE State, DWORD* pValue) override;
|
||||
HRESULT __stdcall CreateStateBlock(D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9** ppSB) override;
|
||||
HRESULT __stdcall BeginStateBlock() override;
|
||||
HRESULT __stdcall EndStateBlock(IDirect3DStateBlock9** ppSB) override;
|
||||
HRESULT __stdcall SetClipStatus(CONST D3DCLIPSTATUS9* pClipStatus) override;
|
||||
HRESULT __stdcall GetClipStatus(D3DCLIPSTATUS9* pClipStatus) override;
|
||||
HRESULT __stdcall GetTexture(DWORD Stage, IDirect3DBaseTexture9** ppTexture) override;
|
||||
HRESULT __stdcall SetTexture(DWORD Stage, IDirect3DBaseTexture9* pTexture) override;
|
||||
HRESULT __stdcall GetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) override;
|
||||
HRESULT __stdcall SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) override;
|
||||
HRESULT __stdcall GetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD* pValue) override;
|
||||
HRESULT __stdcall SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) override;
|
||||
HRESULT __stdcall ValidateDevice(DWORD* pNumPasses) override;
|
||||
HRESULT __stdcall SetPaletteEntries(UINT PaletteNumber,CONST PALETTEENTRY* pEntries) override;
|
||||
HRESULT __stdcall GetPaletteEntries(UINT PaletteNumber, PALETTEENTRY* pEntries) override;
|
||||
HRESULT __stdcall SetCurrentTexturePalette(UINT PaletteNumber) override;
|
||||
HRESULT __stdcall GetCurrentTexturePalette(UINT* PaletteNumber) override;
|
||||
HRESULT __stdcall SetScissorRect(CONST RECT* pRect) override;
|
||||
HRESULT __stdcall GetScissorRect(RECT* pRect) override;
|
||||
HRESULT __stdcall SetSoftwareVertexProcessing(BOOL bSoftware) override;
|
||||
BOOL __stdcall GetSoftwareVertexProcessing() override;
|
||||
HRESULT __stdcall SetNPatchMode(float nSegments) override;
|
||||
float __stdcall GetNPatchMode() override;
|
||||
HRESULT __stdcall DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) override;
|
||||
HRESULT __stdcall DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) override;
|
||||
HRESULT __stdcall DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount,CONST void* pVertexStreamZeroData, UINT VertexStreamZeroStride) override;
|
||||
HRESULT __stdcall DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, UINT PrimitiveCount,CONST void* pIndexData, D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
|
||||
UINT VertexStreamZeroStride) override;
|
||||
HRESULT __stdcall ProcessVertices(UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9* pDestBuffer, IDirect3DVertexDeclaration9* pVertexDecl, DWORD Flags) override;
|
||||
HRESULT __stdcall CreateVertexDeclaration(CONST D3DVERTEXELEMENT9* pVertexElements, IDirect3DVertexDeclaration9** ppDecl) override;
|
||||
HRESULT __stdcall SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl) override;
|
||||
HRESULT __stdcall GetVertexDeclaration(IDirect3DVertexDeclaration9** ppDecl) override;
|
||||
HRESULT __stdcall SetFVF(DWORD FVF) override;
|
||||
HRESULT __stdcall GetFVF(DWORD* pFVF) override;
|
||||
HRESULT __stdcall CreateVertexShader(CONST DWORD* pFunction, IDirect3DVertexShader9** ppShader) override;
|
||||
HRESULT __stdcall SetVertexShader(IDirect3DVertexShader9* pShader) override;
|
||||
HRESULT __stdcall GetVertexShader(IDirect3DVertexShader9** ppShader) override;
|
||||
HRESULT __stdcall SetVertexShaderConstantF(UINT StartRegister,CONST float* pConstantData, UINT Vector4fCount) override;
|
||||
HRESULT __stdcall GetVertexShaderConstantF(UINT StartRegister, float* pConstantData, UINT Vector4fCount) override;
|
||||
HRESULT __stdcall SetVertexShaderConstantI(UINT StartRegister,CONST int* pConstantData, UINT Vector4iCount) override;
|
||||
HRESULT __stdcall GetVertexShaderConstantI(UINT StartRegister, int* pConstantData, UINT Vector4iCount) override;
|
||||
HRESULT __stdcall SetVertexShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData, UINT BoolCount) override;
|
||||
HRESULT __stdcall GetVertexShaderConstantB(UINT StartRegister, BOOL* pConstantData, UINT BoolCount) override;
|
||||
HRESULT __stdcall SetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride) override;
|
||||
HRESULT __stdcall GetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* OffsetInBytes, UINT* pStride) override;
|
||||
HRESULT __stdcall SetStreamSourceFreq(UINT StreamNumber, UINT Divider) override;
|
||||
HRESULT __stdcall GetStreamSourceFreq(UINT StreamNumber, UINT* Divider) override;
|
||||
HRESULT __stdcall SetIndices(IDirect3DIndexBuffer9* pIndexData) override;
|
||||
HRESULT __stdcall GetIndices(IDirect3DIndexBuffer9** ppIndexData) override;
|
||||
HRESULT __stdcall CreatePixelShader(CONST DWORD* pFunction, IDirect3DPixelShader9** ppShader) override;
|
||||
HRESULT __stdcall SetPixelShader(IDirect3DPixelShader9* pShader) override;
|
||||
HRESULT __stdcall GetPixelShader(IDirect3DPixelShader9** ppShader) override;
|
||||
HRESULT __stdcall SetPixelShaderConstantF(UINT StartRegister,CONST float* pConstantData, UINT Vector4fCount) override;
|
||||
HRESULT __stdcall GetPixelShaderConstantF(UINT StartRegister, float* pConstantData, UINT Vector4fCount) override;
|
||||
HRESULT __stdcall SetPixelShaderConstantI(UINT StartRegister,CONST int* pConstantData, UINT Vector4iCount) override;
|
||||
HRESULT __stdcall GetPixelShaderConstantI(UINT StartRegister, int* pConstantData, UINT Vector4iCount) override;
|
||||
HRESULT __stdcall SetPixelShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData, UINT BoolCount) override;
|
||||
HRESULT __stdcall GetPixelShaderConstantB(UINT StartRegister, BOOL* pConstantData, UINT BoolCount) override;
|
||||
HRESULT __stdcall DrawRectPatch(UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) override;
|
||||
HRESULT __stdcall DrawTriPatch(UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) override;
|
||||
HRESULT __stdcall DeletePatch(UINT Handle) override;
|
||||
HRESULT __stdcall CreateQuery(D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) override;
|
||||
|
||||
|
||||
|
||||
HRESULT __stdcall CheckDeviceState(HWND hWindow) override;
|
||||
HRESULT __stdcall CheckResourceResidency(IDirect3DResource9** pResourceArray, UINT32 NumResources) override;
|
||||
HRESULT __stdcall ComposeRects(IDirect3DSurface9* pSource, IDirect3DSurface9* pDestination, IDirect3DVertexBuffer9* pSrcRectDescriptors, UINT NumRects, IDirect3DVertexBuffer9* pDstRectDescriptors, D3DCOMPOSERECTSOP Operation, INT XOffset,
|
||||
INT YOffset) override;
|
||||
HRESULT __stdcall CreateDepthStencilSurfaceEx(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle, DWORD Usage) override;
|
||||
HRESULT __stdcall CreateOffscreenPlainSurfaceEx(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle, DWORD Usage) override;
|
||||
HRESULT __stdcall CreateRenderTargetEx(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle, DWORD Usage) override;
|
||||
HRESULT __stdcall GetDisplayModeEx(UINT iSwapChain, D3DDISPLAYMODEEX* pMode, D3DDISPLAYROTATION* pRotation) override;
|
||||
HRESULT __stdcall GetGPUThreadPriority(INT* pPriority) override;
|
||||
HRESULT __stdcall GetMaximumFrameLatency(UINT* pMaxLatency) override;
|
||||
HRESULT __stdcall PresentEx(const RECT* pSourceRect, const RECT* pDestRect, HWND hDestWindowOverride, const RGNDATA* pDirtyRegion, DWORD dwFlags) override;
|
||||
HRESULT __stdcall ResetEx(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode) override;
|
||||
HRESULT __stdcall SetConvolutionMonoKernel(UINT Width, UINT Height, float* RowWeights, float* ColumnWeights) override;
|
||||
HRESULT __stdcall SetGPUThreadPriority(INT pPriority) override;
|
||||
HRESULT __stdcall SetMaximumFrameLatency(UINT pMaxLatency) override;
|
||||
//HRESULT __stdcall TestCooperativeLevel();
|
||||
HRESULT __stdcall WaitForVBlank(UINT SwapChainIndex) override;
|
||||
|
||||
|
||||
// END: The original DX9 function definitions
|
||||
|
||||
TextureClient* GetuMod_Client() { return uMod_Client; }
|
||||
|
||||
uMod_IDirect3DTexture9* GetLastCreatedTexture() { return LastCreatedTexture; }
|
||||
|
||||
void SetLastCreatedTexture(uMod_IDirect3DTexture9* pTexture)
|
||||
{
|
||||
LastCreatedTexture = pTexture;
|
||||
}
|
||||
|
||||
uMod_IDirect3DVolumeTexture9* GetLastCreatedVolumeTexture() { return LastCreatedVolumeTexture; }
|
||||
|
||||
void SetLastCreatedVolumeTexture(uMod_IDirect3DVolumeTexture9* pTexture)
|
||||
{
|
||||
LastCreatedVolumeTexture = pTexture;
|
||||
}
|
||||
|
||||
uMod_IDirect3DCubeTexture9* GetLastCreatedCubeTexture() { return LastCreatedCubeTexture; }
|
||||
|
||||
void SetLastCreatedCubeTexture(uMod_IDirect3DCubeTexture9* pTexture)
|
||||
{
|
||||
LastCreatedCubeTexture = pTexture;
|
||||
}
|
||||
|
||||
private:
|
||||
IDirect3DDevice9Ex* m_pIDirect3DDevice9Ex;
|
||||
|
||||
int BackBufferCount;
|
||||
bool NormalRendering = true;
|
||||
|
||||
int uMod_Reference = 1;
|
||||
|
||||
uMod_IDirect3DTexture9* LastCreatedTexture = nullptr;
|
||||
uMod_IDirect3DVolumeTexture9* LastCreatedVolumeTexture = nullptr;
|
||||
uMod_IDirect3DCubeTexture9* LastCreatedCubeTexture = nullptr;
|
||||
|
||||
TextureClient* uMod_Client = nullptr;
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d9.h>
|
||||
#include "Defines.h"
|
||||
|
||||
struct TextureFileStruct;
|
||||
interface uMod_IDirect3DTexture9 : IDirect3DTexture9 {
|
||||
uMod_IDirect3DTexture9(IDirect3DTexture9** ppTex, IDirect3DDevice9* pIDirect3DDevice9)
|
||||
: m_D3Dtex(*ppTex),
|
||||
m_D3Ddev(pIDirect3DDevice9)
|
||||
{}
|
||||
|
||||
virtual ~uMod_IDirect3DTexture9() = default;
|
||||
|
||||
// callback interface
|
||||
IDirect3DTexture9* m_D3Dtex = nullptr;
|
||||
uMod_IDirect3DTexture9* CrossRef_D3Dtex = nullptr;
|
||||
IDirect3DDevice9* m_D3Ddev = nullptr;
|
||||
TextureFileStruct* Reference = nullptr;
|
||||
HashTuple Hash = {};
|
||||
bool FAKE = false;
|
||||
|
||||
// original interface
|
||||
STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj) override;
|
||||
STDMETHOD_(ULONG, AddRef)() override;
|
||||
STDMETHOD_(ULONG, Release)() override;
|
||||
STDMETHOD(GetDevice)(IDirect3DDevice9** ppDevice) override;
|
||||
STDMETHOD(SetPrivateData)(REFGUID refguid,CONST void* pData, DWORD SizeOfData, DWORD Flags) override;
|
||||
STDMETHOD(GetPrivateData)(REFGUID refguid, void* pData, DWORD* pSizeOfData) override;
|
||||
STDMETHOD(FreePrivateData)(REFGUID refguid) override;
|
||||
STDMETHOD_(DWORD, SetPriority)(DWORD PriorityNew) override;
|
||||
STDMETHOD_(DWORD, GetPriority)() override;
|
||||
STDMETHOD_(void, PreLoad)() override;
|
||||
STDMETHOD_(D3DRESOURCETYPE, GetType)() override;
|
||||
STDMETHOD_(DWORD, SetLOD)(DWORD LODNew) override;
|
||||
STDMETHOD_(DWORD, GetLOD)() override;
|
||||
STDMETHOD_(DWORD, GetLevelCount)() override;
|
||||
STDMETHOD(SetAutoGenFilterType)(D3DTEXTUREFILTERTYPE FilterType) override;
|
||||
STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)() override;
|
||||
STDMETHOD_(void, GenerateMipSubLevels)() override;
|
||||
STDMETHOD(GetLevelDesc)(UINT Level, D3DSURFACE_DESC* pDesc) override;
|
||||
STDMETHOD(GetSurfaceLevel)(UINT Level, IDirect3DSurface9** ppSurfaceLevel) override;
|
||||
STDMETHOD(LockRect)(UINT Level, D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect, DWORD Flags) override;
|
||||
STDMETHOD(UnlockRect)(UINT Level) override;
|
||||
STDMETHOD(AddDirtyRect)(CONST RECT* pDirtyRect) override;
|
||||
|
||||
[[nodiscard]] HashTuple GetHash() const;
|
||||
};
|
||||
@@ -1,47 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d9.h>
|
||||
|
||||
interface uMod_IDirect3DVolumeTexture9 : IDirect3DVolumeTexture9 {
|
||||
uMod_IDirect3DVolumeTexture9(IDirect3DVolumeTexture9** ppTex, IDirect3DDevice9* pIDirect3DDevice9)
|
||||
: m_D3Dtex(*ppTex),
|
||||
m_D3Ddev(pIDirect3DDevice9)
|
||||
{}
|
||||
|
||||
virtual ~uMod_IDirect3DVolumeTexture9() = default;
|
||||
|
||||
// callback interface
|
||||
IDirect3DVolumeTexture9* m_D3Dtex = nullptr;
|
||||
uMod_IDirect3DVolumeTexture9* CrossRef_D3Dtex = nullptr;
|
||||
IDirect3DDevice9* m_D3Ddev = nullptr;
|
||||
TextureFileStruct* Reference = nullptr;
|
||||
HashTuple Hash = {};
|
||||
bool FAKE = false;
|
||||
|
||||
// original interface
|
||||
STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj) override;
|
||||
STDMETHOD_(ULONG, AddRef)() override;
|
||||
STDMETHOD_(ULONG, Release)() override;
|
||||
STDMETHOD(GetDevice)(IDirect3DDevice9** ppDevice) override;
|
||||
STDMETHOD(SetPrivateData)(REFGUID refguid,CONST void* pData, DWORD SizeOfData, DWORD Flags) override;
|
||||
STDMETHOD(GetPrivateData)(REFGUID refguid, void* pData, DWORD* pSizeOfData) override;
|
||||
STDMETHOD(FreePrivateData)(REFGUID refguid) override;
|
||||
STDMETHOD_(DWORD, SetPriority)(DWORD PriorityNew) override;
|
||||
STDMETHOD_(DWORD, GetPriority)() override;
|
||||
STDMETHOD_(void, PreLoad)() override;
|
||||
STDMETHOD_(D3DRESOURCETYPE, GetType)() override;
|
||||
STDMETHOD_(DWORD, SetLOD)(DWORD LODNew) override;
|
||||
STDMETHOD_(DWORD, GetLOD)() override;
|
||||
STDMETHOD_(DWORD, GetLevelCount)() override;
|
||||
STDMETHOD(SetAutoGenFilterType)(D3DTEXTUREFILTERTYPE FilterType) override;
|
||||
STDMETHOD_(D3DTEXTUREFILTERTYPE, GetAutoGenFilterType)() override;
|
||||
STDMETHOD_(void, GenerateMipSubLevels)() override;
|
||||
STDMETHOD(AddDirtyBox)(CONST D3DBOX* pDirtyBox) override;
|
||||
STDMETHOD(GetLevelDesc)(UINT Level, D3DVOLUME_DESC* pDesc) override;
|
||||
STDMETHOD(GetVolumeLevel)(UINT Level, IDirect3DVolume9** ppVolumeLevel) override;
|
||||
STDMETHOD(LockBox)(UINT Level, D3DLOCKED_BOX* pLockedVolume, CONST D3DBOX* pBox, DWORD Flags) override;
|
||||
STDMETHOD(UnlockBox)(UINT Level) override;
|
||||
|
||||
|
||||
[[nodiscard]] HashTuple GetHash() const;
|
||||
};
|
||||
@@ -13,7 +13,8 @@ import TextureFunction;
|
||||
namespace {
|
||||
bool use_64_bit_crc = false;
|
||||
|
||||
HashType GetCrcFromFilename(const std::string& filename) {
|
||||
HashType GetCrcFromFilename(const std::string& filename)
|
||||
{
|
||||
const static std::regex re(R"(0[xX][0-9a-fA-F]{4,16})", std::regex::optimize);
|
||||
std::smatch match;
|
||||
if (!std::regex_search(filename, match, re)) {
|
||||
@@ -39,7 +40,8 @@ namespace {
|
||||
}
|
||||
|
||||
namespace HashCheck {
|
||||
export bool Use64BitCrc() {
|
||||
export bool Use64BitCrc()
|
||||
{
|
||||
return use_64_bit_crc;
|
||||
}
|
||||
}
|
||||
@@ -52,8 +54,7 @@ export class ModfileLoader {
|
||||
0x74, 0x61, 0x67, 0x5B, 0x60, 0x70, 0x45, 0x74,
|
||||
0x5C, 0x22, 0x74, 0x5D, 0x6E, 0x6A, 0x73, 0x41,
|
||||
0x77, 0x6E, 0x46, 0x47, 0x77, 0x49, 0x0C, 0x4B,
|
||||
0x46, 0x6F
|
||||
};
|
||||
0x46, 0x6F};
|
||||
|
||||
public:
|
||||
ModfileLoader(const std::filesystem::path& fileName);
|
||||
@@ -61,7 +62,6 @@ public:
|
||||
std::vector<TexEntry> GetContents() const;
|
||||
|
||||
private:
|
||||
|
||||
std::vector<TexEntry> GetTpfContents() const;
|
||||
|
||||
std::vector<TexEntry> GetFileContents() const;
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
|
||||
// in the other zip libraries, these had to be cut off, with libzip we need to zero them out
|
||||
// cutting them off makes the archive invalid
|
||||
//data.resize(last_zero);
|
||||
// data.resize(last_zero);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
+362
-266
@@ -2,10 +2,11 @@ module;
|
||||
|
||||
#include "Main.h"
|
||||
#include "Error.h"
|
||||
#include "uMod_IDirect3DTexture9.h"
|
||||
#include "D3D9State.h"
|
||||
#include <DDSTextureLoader/DDSTextureLoader9.h>
|
||||
#include <DirectXTex/DirectXTex.h>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
export module TextureClient;
|
||||
import TextureFunction;
|
||||
@@ -14,27 +15,51 @@ import ModfileLoader;
|
||||
export std::vector<std::pair<std::string, std::string>> modlists_contents;
|
||||
|
||||
struct PendingOp {
|
||||
enum class Kind { Add, Remove };
|
||||
enum class Kind {
|
||||
Add,
|
||||
Remove
|
||||
};
|
||||
Kind kind;
|
||||
HashType hash;
|
||||
std::vector<BYTE> data;
|
||||
};
|
||||
|
||||
// Couples a value with the mutex guarding it; the value is only reachable while
|
||||
// the lock is held.
|
||||
template <class T>
|
||||
class Guarded {
|
||||
std::mutex mutex;
|
||||
T value;
|
||||
|
||||
public:
|
||||
template <class Fn>
|
||||
auto with(Fn&& fn)
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
return fn(value);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* An object of this class is owned by each d3d9 device.
|
||||
* All other functions are called from the render thread instance of the game itself.
|
||||
* Owned by each d3d9 device (see D3D9Hooks.cpp). Holds the side-state for every
|
||||
* texture and performs the actual modding. The On*() methods are the vtable-hook
|
||||
* entry points, all driven by the game's render thread.
|
||||
*/
|
||||
export class TextureClient {
|
||||
public:
|
||||
TextureClient(IDirect3DDevice9* device);
|
||||
~TextureClient();
|
||||
|
||||
int AddTexture(uModTexturePtr auto pTexture);
|
||||
int RemoveTexture(uModTexturePtr auto pTexture); //called from uMod_IDirect3DTexture9::Release()
|
||||
int LookUpToMod(uModTexturePtr auto pTexture);
|
||||
// called at the end AddTexture(...) and from Device->UpdateTexture(...)
|
||||
// Called from the hooked vtable slots:
|
||||
TexState* OnCreateTexture(IDirect3DBaseTexture9* texture, TexType type);
|
||||
void OnBeginScene();
|
||||
// The fake replacement when `texture` is a modded original, else `texture`.
|
||||
IDirect3DBaseTexture9* ResolveBinding(IDirect3DBaseTexture9* texture);
|
||||
// For GetTexture: the original behind one of our fakes, or nullptr.
|
||||
IDirect3DBaseTexture9* ResolveOriginalFromFake(IDirect3DBaseTexture9* texture);
|
||||
void OnUpdateTexture(IDirect3DBaseTexture9* source, IDirect3DBaseTexture9* destination);
|
||||
void OnReleaseTexture(IDirect3DBaseTexture9* texture); // called once the real refcount hit zero
|
||||
|
||||
int MergeUpdate(); //called from uMod_IDirect3DDevice9::BeginScene()
|
||||
void Initialize();
|
||||
|
||||
void EnqueueAdd(HashType hash, std::vector<BYTE> data);
|
||||
@@ -44,55 +69,80 @@ public:
|
||||
static int RemoveFile(const std::filesystem::path& path);
|
||||
static std::vector<std::filesystem::path> GetFiles();
|
||||
|
||||
std::vector<uMod_IDirect3DTexture9*> OriginalTextures;
|
||||
// stores the pointer to the uMod_IDirect3DTexture9 objects created by the game
|
||||
std::vector<uMod_IDirect3DVolumeTexture9*> OriginalVolumeTextures;
|
||||
// stores the pointer to the uMod_IDirect3DVolumeTexture9 objects created by the game
|
||||
std::vector<uMod_IDirect3DCubeTexture9*> OriginalCubeTextures;
|
||||
// stores the pointer to the uMod_IDirect3DCubeTexture9 objects created by the game
|
||||
// The texture Release hook has only a texture pointer, so it finds its client here.
|
||||
static TextureClient* CurrentClient();
|
||||
|
||||
private:
|
||||
IDirect3DDevice9* D3D9Device;
|
||||
// Cached info about whether this id a dx9ex device or not; used for proxy functions
|
||||
bool isDirectXExDevice = false;
|
||||
|
||||
// DX9 proxy functions
|
||||
void SetLastCreatedTexture(uMod_IDirect3DTexture9*);
|
||||
void SetLastCreatedVolumeTexture(uMod_IDirect3DVolumeTexture9*);
|
||||
void SetLastCreatedCubeTexture(uMod_IDirect3DCubeTexture9*);
|
||||
// Side-state keyed by real texture pointer: the game's textures vs. our fakes.
|
||||
std::recursive_mutex registry_mutex;
|
||||
std::unordered_map<IDirect3DBaseTexture9*, TexState*> originals;
|
||||
std::unordered_map<IDirect3DBaseTexture9*, TexState*> fakes;
|
||||
|
||||
// Hashed one creation later, once the game has filled it with data.
|
||||
IDirect3DBaseTexture9* last_created[3] = {};
|
||||
|
||||
bool loading_fake = false; // set while LoadTexture() drives CreateTexture internally
|
||||
bool shutting_down = false; // set in ~TextureClient so the Release hook stops touching us
|
||||
bool should_update = false;
|
||||
|
||||
int AddTexture(IDirect3DBaseTexture9* texture); // hash a freshly filled original + look up its mod
|
||||
int LookUpToMod(TexState* state); // switch in a fake if a mod matches the hash
|
||||
int LoadTexture(TextureFileStruct* file_in_memory, IDirect3DBaseTexture9** ppTexture, TexState** ppState);
|
||||
|
||||
static void Switch(TexState* original, TexState* fake);
|
||||
static void Unswitch(TexState* original);
|
||||
void UnswitchAndRelease(TexState* original); // unswitch + release our fake
|
||||
|
||||
int MergeUpdate();
|
||||
|
||||
int LockMutex();
|
||||
int UnlockMutex();
|
||||
HANDLE hMutex;
|
||||
|
||||
std::mutex pending_mutex;
|
||||
std::vector<PendingOp> pending_ops;
|
||||
Guarded<std::vector<PendingOp>> pending_ops;
|
||||
void ProcessPendingOps();
|
||||
void RemoveModdedTexture(HashType hash);
|
||||
|
||||
std::unordered_map<HashType, gsl::owner<TextureFileStruct*>> modded_textures;
|
||||
// array which stores the file in memory and the hash of each texture to be modded
|
||||
|
||||
// called if a target texture is found
|
||||
int LoadTexture(TextureFileStruct* file_in_memory, uModTexturePtrPtr auto ppTexture);
|
||||
std::unordered_map<HashType, gsl::owner<TextureFileStruct*>> modded_textures; // hash -> mod file in memory
|
||||
|
||||
static void LoadStartupModlists();
|
||||
|
||||
// Enqueue an Add per distinct non-zero hash, free the structs, return the hashes
|
||||
// in load order; accumulates moved bytes into loaded_bytes when given.
|
||||
static std::vector<HashType> IngestModfile(std::vector<gsl::owner<TextureFileStruct*>>& texture_file_structs, uint64_t* loaded_bytes = nullptr);
|
||||
|
||||
// Kept in load order, which is priority order: on a hash collision the
|
||||
// earlier file wins (see ProcessPendingOps).
|
||||
struct LoadedFile {
|
||||
std::filesystem::path path;
|
||||
std::vector<HashType> hashes;
|
||||
};
|
||||
|
||||
static inline std::mutex global_mutex;
|
||||
static inline TextureClient* current_client = nullptr;
|
||||
static inline std::map<std::filesystem::path, std::vector<HashType>> loaded_files;
|
||||
// A vector, not a map: tens of mods at most, and their order is meaningful.
|
||||
static inline std::vector<LoadedFile> loaded_files;
|
||||
|
||||
// Caller holds global_mutex; path must already be absolute.
|
||||
static std::vector<LoadedFile>::iterator FindLoadedFile(const std::filesystem::path& absolute_path)
|
||||
{
|
||||
return std::ranges::find(loaded_files, absolute_path, &LoadedFile::path);
|
||||
}
|
||||
};
|
||||
|
||||
TextureClient* TextureClient::CurrentClient()
|
||||
{
|
||||
std::lock_guard lk(global_mutex);
|
||||
return current_client;
|
||||
}
|
||||
|
||||
TextureClient::TextureClient(IDirect3DDevice9* device)
|
||||
{
|
||||
Message("TextureClient::TextureClient(): %p\n", this);
|
||||
D3D9Device = device;
|
||||
|
||||
void* cpy;
|
||||
isDirectXExDevice = D3D9Device->QueryInterface(IID_IDirect3DTexture9, &cpy) == 0x01000001L;
|
||||
|
||||
hMutex = CreateMutex(nullptr, false, nullptr);
|
||||
|
||||
std::lock_guard lk(global_mutex);
|
||||
@@ -107,6 +157,23 @@ TextureClient::~TextureClient()
|
||||
std::lock_guard lk(global_mutex);
|
||||
if (current_client == this) current_client = nullptr;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard lk(registry_mutex);
|
||||
shutting_down = true; // the texture Release hook now no-ops for our textures
|
||||
|
||||
// Drop side-state but don't Release the textures: the game already released
|
||||
// its originals (and our fakes with them), and the device may be gone.
|
||||
for (const auto state : fakes | std::views::values) {
|
||||
delete state;
|
||||
}
|
||||
fakes.clear();
|
||||
for (const auto state : originals | std::views::values) {
|
||||
delete state;
|
||||
}
|
||||
originals.clear();
|
||||
}
|
||||
|
||||
if (hMutex != nullptr) {
|
||||
CloseHandle(hMutex);
|
||||
}
|
||||
@@ -116,13 +183,216 @@ TextureClient::~TextureClient()
|
||||
modded_textures.clear();
|
||||
}
|
||||
|
||||
void TextureClient::Switch(TexState* original, TexState* fake)
|
||||
{
|
||||
original->partner = fake;
|
||||
fake->partner = original;
|
||||
}
|
||||
|
||||
void TextureClient::Unswitch(TexState* original)
|
||||
{
|
||||
if (original->partner != nullptr) {
|
||||
original->partner->partner = nullptr;
|
||||
original->partner = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureClient::UnswitchAndRelease(TexState* original)
|
||||
{
|
||||
TexState* fake = original->partner;
|
||||
if (fake == nullptr) return;
|
||||
Unswitch(original); // detach before releasing so the fake's Release hook won't touch `original`
|
||||
if (fake->real) fake->real->Release(); // re-enters OnReleaseTexture(fake), which frees its state
|
||||
}
|
||||
|
||||
TexState* TextureClient::OnCreateTexture(IDirect3DBaseTexture9* texture, TexType type)
|
||||
{
|
||||
std::lock_guard lk(registry_mutex);
|
||||
|
||||
const auto state = new TexState();
|
||||
state->real = texture;
|
||||
state->device = D3D9Device;
|
||||
state->type = type;
|
||||
|
||||
if (loading_fake) {
|
||||
// A replacement we're creating: track as a fake, skip the originals bookkeeping.
|
||||
state->isFake = true;
|
||||
fakes.emplace(texture, state);
|
||||
return state;
|
||||
}
|
||||
|
||||
originals.emplace(texture, state);
|
||||
|
||||
// The previous texture of this type is now filled, so hash it.
|
||||
if (const auto last = last_created[static_cast<int>(type)]) {
|
||||
AddTexture(last);
|
||||
}
|
||||
last_created[static_cast<int>(type)] = texture;
|
||||
return state;
|
||||
}
|
||||
|
||||
int TextureClient::AddTexture(IDirect3DBaseTexture9* texture)
|
||||
{
|
||||
const auto it = originals.find(texture);
|
||||
if (it == originals.end()) return RETURN_OK;
|
||||
const auto state = it->second;
|
||||
|
||||
// No longer pending.
|
||||
if (last_created[static_cast<int>(state->type)] == texture) {
|
||||
last_created[static_cast<int>(state->type)] = nullptr;
|
||||
}
|
||||
|
||||
if (gl_ErrorState & uMod_ERROR_FATAL) {
|
||||
return RETURN_FATAL_ERROR;
|
||||
}
|
||||
|
||||
state->hash = GetTextureHash(state);
|
||||
if (!state->hash) {
|
||||
return RETURN_FATAL_ERROR;
|
||||
}
|
||||
|
||||
return LookUpToMod(state); // check if this texture should be modded
|
||||
}
|
||||
|
||||
int TextureClient::LookUpToMod(TexState* state)
|
||||
{
|
||||
Message("TextureClient::LookUpToMod( %p): hash: %#lX\n", state->real, state->hash);
|
||||
if (state->partner != nullptr)
|
||||
return RETURN_OK; // already switched
|
||||
|
||||
auto found = modded_textures.find(state->hash.crc32);
|
||||
if (found == modded_textures.end())
|
||||
if (found = modded_textures.find(state->hash.crc64), !state->hash.crc64 || found == modded_textures.end())
|
||||
return RETURN_OK;
|
||||
|
||||
const auto textureFileStruct = found->second;
|
||||
|
||||
IDirect3DBaseTexture9* fake_texture = nullptr;
|
||||
TexState* fake_state = nullptr;
|
||||
if (const int ret = LoadTexture(textureFileStruct, &fake_texture, &fake_state); ret != RETURN_OK)
|
||||
return ret;
|
||||
|
||||
Switch(state, fake_state);
|
||||
fake_state->reference = textureFileStruct;
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
int TextureClient::LoadTexture(TextureFileStruct* file_in_memory, IDirect3DBaseTexture9** ppTexture, TexState** ppState)
|
||||
{
|
||||
Message("LoadTexture( %p, %#lX): %p\n", file_in_memory, file_in_memory->crc_hash, this);
|
||||
*ppTexture = nullptr;
|
||||
*ppState = nullptr;
|
||||
|
||||
// CreateDDSTextureFromMemoryEx calls the hooked CreateTexture; loading_fake
|
||||
// makes that hook register the result as a fake, not a game original.
|
||||
IDirect3DTexture9* texture = nullptr;
|
||||
loading_fake = true;
|
||||
const auto ret = DirectX::CreateDDSTextureFromMemoryEx(
|
||||
D3D9Device,
|
||||
file_in_memory->data.data(),
|
||||
file_in_memory->data.size(),
|
||||
0, D3DPOOL_MANAGED, false,
|
||||
&texture);
|
||||
loading_fake = false;
|
||||
|
||||
if (ret != D3D_OK || texture == nullptr) {
|
||||
Warning("LoadDDSTexture (%p, %#lX): FAILED ret: \n", file_in_memory->data.data(), file_in_memory->crc_hash, ret);
|
||||
return RETURN_TEXTURE_NOT_LOADED;
|
||||
}
|
||||
|
||||
const auto fake = static_cast<IDirect3DBaseTexture9*>(texture);
|
||||
const auto state_it = fakes.find(fake);
|
||||
ASSERT(state_it != fakes.end()); // must have been registered by the CreateTexture hook
|
||||
*ppTexture = fake;
|
||||
*ppState = state_it->second;
|
||||
|
||||
Message("LoadTexture (%p, %#lX): DONE\n", fake, file_in_memory->crc_hash);
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
IDirect3DBaseTexture9* TextureClient::ResolveBinding(IDirect3DBaseTexture9* texture)
|
||||
{
|
||||
if (texture == nullptr) return nullptr;
|
||||
std::lock_guard lk(registry_mutex);
|
||||
const auto it = originals.find(texture);
|
||||
if (it != originals.end() && it->second->partner != nullptr) {
|
||||
return it->second->partner->real; // bind the fake in place of the original
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
IDirect3DBaseTexture9* TextureClient::ResolveOriginalFromFake(IDirect3DBaseTexture9* texture)
|
||||
{
|
||||
if (texture == nullptr) return nullptr;
|
||||
std::lock_guard lk(registry_mutex);
|
||||
const auto it = fakes.find(texture);
|
||||
if (it != fakes.end() && it->second->partner != nullptr) {
|
||||
return it->second->partner->real;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TextureClient::OnBeginScene()
|
||||
{
|
||||
{
|
||||
std::lock_guard lk(registry_mutex);
|
||||
for (int type = 0; type < 3; ++type) {
|
||||
if (last_created[type] != nullptr) {
|
||||
AddTexture(last_created[type]); // hashes + clears the slot
|
||||
}
|
||||
}
|
||||
}
|
||||
MergeUpdate();
|
||||
}
|
||||
|
||||
void TextureClient::OnUpdateTexture(IDirect3DBaseTexture9* source, IDirect3DBaseTexture9* destination)
|
||||
{
|
||||
// The copy already happened; re-hash both textures and re-run the mod lookup.
|
||||
std::lock_guard lk(registry_mutex);
|
||||
|
||||
auto refresh = [this](IDirect3DBaseTexture9* texture) {
|
||||
const auto it = originals.find(texture);
|
||||
if (it == originals.end()) return;
|
||||
const auto state = it->second;
|
||||
const auto hash = GetTextureHash(state);
|
||||
if (hash == state->hash) return; // unchanged
|
||||
state->hash = hash;
|
||||
if (state->partner != nullptr) UnswitchAndRelease(state);
|
||||
if (hash) LookUpToMod(state);
|
||||
};
|
||||
refresh(source);
|
||||
refresh(destination);
|
||||
}
|
||||
|
||||
void TextureClient::OnReleaseTexture(IDirect3DBaseTexture9* texture)
|
||||
{
|
||||
std::lock_guard lk(registry_mutex);
|
||||
if (shutting_down) return; // ~TextureClient is tearing everything down itself
|
||||
|
||||
// A fake of ours being released (either by us during cleanup, or transitively).
|
||||
if (const auto fit = fakes.find(texture); fit != fakes.end()) {
|
||||
const auto state = fit->second;
|
||||
if (state->partner != nullptr) state->partner->partner = nullptr;
|
||||
fakes.erase(fit);
|
||||
delete state;
|
||||
return;
|
||||
}
|
||||
|
||||
// A game texture (original) reaching zero references.
|
||||
if (const auto oit = originals.find(texture); oit != originals.end()) {
|
||||
const auto state = oit->second;
|
||||
if (last_created[static_cast<int>(state->type)] == texture) {
|
||||
last_created[static_cast<int>(state->type)] = nullptr;
|
||||
}
|
||||
originals.erase(oit);
|
||||
UnswitchAndRelease(state); // release the fake we held for it, if any
|
||||
delete state;
|
||||
}
|
||||
}
|
||||
|
||||
int TextureClient::MergeUpdate()
|
||||
{
|
||||
bool has_pending;
|
||||
{
|
||||
std::lock_guard lk(pending_mutex);
|
||||
has_pending = !pending_ops.empty();
|
||||
}
|
||||
const bool has_pending = pending_ops.with([](auto& ops) { return !ops.empty(); });
|
||||
if (!should_update && !has_pending) return RETURN_OK;
|
||||
if (const int ret = LockMutex()) {
|
||||
gl_ErrorState |= uMod_ERROR_TEXTURE;
|
||||
@@ -133,19 +403,12 @@ int TextureClient::MergeUpdate()
|
||||
|
||||
ProcessPendingOps();
|
||||
|
||||
for (const auto pTexture : OriginalTextures) {
|
||||
if (pTexture->CrossRef_D3Dtex == nullptr) {
|
||||
LookUpToMod(pTexture);
|
||||
}
|
||||
}
|
||||
for (const auto pTexture : OriginalVolumeTextures) {
|
||||
if (pTexture->CrossRef_D3Dtex == nullptr) {
|
||||
LookUpToMod(pTexture);
|
||||
}
|
||||
}
|
||||
for (const auto pTexture : OriginalCubeTextures) {
|
||||
if (pTexture->CrossRef_D3Dtex == nullptr) {
|
||||
LookUpToMod(pTexture);
|
||||
{
|
||||
std::lock_guard lk(registry_mutex);
|
||||
for (const auto state : originals | std::views::values) {
|
||||
if (state->partner == nullptr && state->hash) {
|
||||
LookUpToMod(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,24 +419,19 @@ int TextureClient::MergeUpdate()
|
||||
void TextureClient::EnqueueAdd(HashType hash, std::vector<BYTE> data)
|
||||
{
|
||||
if (!hash) return;
|
||||
std::lock_guard lk(pending_mutex);
|
||||
pending_ops.push_back(PendingOp{PendingOp::Kind::Add, hash, std::move(data)});
|
||||
pending_ops.with([&](auto& ops) { ops.push_back(PendingOp{PendingOp::Kind::Add, hash, std::move(data)}); });
|
||||
}
|
||||
|
||||
void TextureClient::EnqueueRemove(HashType hash)
|
||||
{
|
||||
if (!hash) return;
|
||||
std::lock_guard lk(pending_mutex);
|
||||
pending_ops.push_back(PendingOp{PendingOp::Kind::Remove, hash, {}});
|
||||
pending_ops.with([&](auto& ops) { ops.push_back(PendingOp{PendingOp::Kind::Remove, hash, {}}); });
|
||||
}
|
||||
|
||||
void TextureClient::ProcessPendingOps()
|
||||
{
|
||||
std::vector<PendingOp> ops;
|
||||
{
|
||||
std::lock_guard lk(pending_mutex);
|
||||
ops.swap(pending_ops);
|
||||
}
|
||||
pending_ops.with([&](auto& pending) { ops.swap(pending); });
|
||||
for (auto& op : ops) {
|
||||
if (op.kind == PendingOp::Kind::Add) {
|
||||
if (modded_textures.contains(op.hash)) continue;
|
||||
@@ -195,51 +453,27 @@ void TextureClient::RemoveModdedTexture(HashType hash)
|
||||
if (it == modded_textures.end()) return;
|
||||
const auto texture_file_struct = it->second;
|
||||
|
||||
auto unswitch_in = [texture_file_struct](auto& vec) {
|
||||
for (auto* original_texture : vec) {
|
||||
auto* fake_texture = original_texture->CrossRef_D3Dtex;
|
||||
if (fake_texture && fake_texture->Reference == texture_file_struct) {
|
||||
UnswitchTextures(original_texture);
|
||||
fake_texture->Release();
|
||||
{
|
||||
std::lock_guard lk(registry_mutex);
|
||||
for (const auto original : originals | std::views::values) {
|
||||
const auto fake = original->partner;
|
||||
if (fake != nullptr && fake->reference == texture_file_struct) {
|
||||
UnswitchAndRelease(original);
|
||||
}
|
||||
}
|
||||
};
|
||||
unswitch_in(OriginalTextures);
|
||||
unswitch_in(OriginalVolumeTextures);
|
||||
unswitch_in(OriginalCubeTextures);
|
||||
}
|
||||
|
||||
modded_textures.erase(it);
|
||||
delete texture_file_struct;
|
||||
}
|
||||
|
||||
void TextureClient::SetLastCreatedTexture(uMod_IDirect3DTexture9* texture)
|
||||
{
|
||||
if (isDirectXExDevice)
|
||||
return static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->SetLastCreatedTexture(texture);
|
||||
return static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->SetLastCreatedTexture(texture);
|
||||
}
|
||||
|
||||
void TextureClient::SetLastCreatedVolumeTexture(uMod_IDirect3DVolumeTexture9* texture)
|
||||
{
|
||||
if (isDirectXExDevice)
|
||||
return static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->SetLastCreatedVolumeTexture(texture);
|
||||
return static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->SetLastCreatedVolumeTexture(texture);
|
||||
}
|
||||
|
||||
void TextureClient::SetLastCreatedCubeTexture(uMod_IDirect3DCubeTexture9* texture)
|
||||
{
|
||||
if (isDirectXExDevice)
|
||||
return static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->SetLastCreatedCubeTexture(texture);
|
||||
return static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->SetLastCreatedCubeTexture(texture);
|
||||
}
|
||||
|
||||
int TextureClient::LockMutex()
|
||||
{
|
||||
if ((gl_ErrorState & (uMod_ERROR_FATAL | uMod_ERROR_MUTEX))) {
|
||||
return RETURN_NO_MUTEX;
|
||||
}
|
||||
if (WAIT_OBJECT_0 != WaitForSingleObject(hMutex, 100)) {
|
||||
return RETURN_MUTEX_LOCK; //waiting 100ms, to wait infinite pass INFINITE
|
||||
return RETURN_MUTEX_LOCK; // waiting 100ms, to wait infinite pass INFINITE
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
@@ -289,13 +523,31 @@ std::vector<gsl::owner<TextureFileStruct*>> ProcessModfile(const std::filesystem
|
||||
return texture_file_structs;
|
||||
}
|
||||
|
||||
std::vector<HashType> TextureClient::IngestModfile(std::vector<gsl::owner<TextureFileStruct*>>& texture_file_structs, uint64_t* loaded_bytes)
|
||||
{
|
||||
std::vector<HashType> hashes;
|
||||
for (auto* texture_file_struct : texture_file_structs) {
|
||||
const auto hash = texture_file_struct->crc_hash;
|
||||
if (hash && std::ranges::find(hashes, hash) == hashes.end()) {
|
||||
hashes.push_back(hash);
|
||||
if (loaded_bytes) *loaded_bytes += texture_file_struct->data.size();
|
||||
if (current_client) {
|
||||
current_client->EnqueueAdd(hash, std::move(texture_file_struct->data));
|
||||
}
|
||||
}
|
||||
delete texture_file_struct;
|
||||
}
|
||||
texture_file_structs.clear();
|
||||
return hashes;
|
||||
}
|
||||
|
||||
std::vector<std::filesystem::path> TextureClient::GetFiles()
|
||||
{
|
||||
std::lock_guard lk(global_mutex);
|
||||
std::vector<std::filesystem::path> result;
|
||||
result.reserve(loaded_files.size());
|
||||
for (const auto& key : loaded_files | std::views::keys) {
|
||||
result.push_back(key);
|
||||
for (const auto& loaded_file : loaded_files) {
|
||||
result.push_back(loaded_file.path);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -304,10 +556,10 @@ int TextureClient::RemoveFile(const std::filesystem::path& path)
|
||||
{
|
||||
const auto absolute_path = std::filesystem::absolute(path);
|
||||
std::lock_guard lk(global_mutex);
|
||||
const auto it = loaded_files.find(absolute_path);
|
||||
const auto it = FindLoadedFile(absolute_path);
|
||||
if (it == loaded_files.end()) return RETURN_FILE_NOT_LOADED;
|
||||
if (current_client) {
|
||||
for (const auto hash : it->second) {
|
||||
for (const auto hash : it->hashes) {
|
||||
current_client->EnqueueRemove(hash);
|
||||
}
|
||||
}
|
||||
@@ -320,35 +572,25 @@ int TextureClient::AddFile(const std::filesystem::path& path)
|
||||
const auto absolute_path = std::filesystem::absolute(path);
|
||||
{
|
||||
std::lock_guard lk(global_mutex);
|
||||
if (loaded_files.contains(absolute_path)) return RETURN_EXISTS;
|
||||
if (FindLoadedFile(absolute_path) != loaded_files.end()) return RETURN_EXISTS;
|
||||
}
|
||||
if (!std::filesystem::exists(absolute_path)) return RETURN_FILE_NOT_LOADED;
|
||||
|
||||
const auto file_size = std::filesystem::file_size(absolute_path);
|
||||
const auto texture_file_structs = ProcessModfile(absolute_path, file_size > 400'000'000);
|
||||
auto texture_file_structs = ProcessModfile(absolute_path, file_size > 400'000'000);
|
||||
if (texture_file_structs.empty()) return RETURN_FILE_NOT_LOADED;
|
||||
|
||||
std::lock_guard lk(global_mutex);
|
||||
// Re-check under lock; another thread may have loaded the same path concurrently.
|
||||
if (loaded_files.contains(absolute_path)) {
|
||||
for (auto* texture_file_struct : texture_file_structs) delete texture_file_struct;
|
||||
if (FindLoadedFile(absolute_path) != loaded_files.end()) {
|
||||
for (auto* texture_file_struct : texture_file_structs)
|
||||
delete texture_file_struct;
|
||||
return RETURN_EXISTS;
|
||||
}
|
||||
|
||||
std::vector<HashType> hashes;
|
||||
for (auto* texture_file_struct : texture_file_structs) {
|
||||
const auto hash = texture_file_struct->crc_hash;
|
||||
if (hash && std::ranges::find(hashes, hash) == hashes.end()) {
|
||||
hashes.push_back(hash);
|
||||
if (current_client) {
|
||||
current_client->EnqueueAdd(hash, std::move(texture_file_struct->data));
|
||||
}
|
||||
}
|
||||
delete texture_file_struct;
|
||||
}
|
||||
|
||||
auto hashes = IngestModfile(texture_file_structs);
|
||||
if (hashes.empty()) return RETURN_TEXTURE_NOT_LOADED;
|
||||
loaded_files.emplace(absolute_path, std::move(hashes));
|
||||
loaded_files.push_back({absolute_path, std::move(hashes)});
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
@@ -391,26 +633,15 @@ void TextureClient::LoadStartupModlists()
|
||||
auto texture_file_structs = futures[i].get();
|
||||
|
||||
std::lock_guard lk(global_mutex);
|
||||
if (loaded_files.contains(modfiles[i])) {
|
||||
for (const auto* texture_file_struct : texture_file_structs) delete texture_file_struct;
|
||||
if (FindLoadedFile(modfiles[i]) != loaded_files.end()) {
|
||||
for (const auto* texture_file_struct : texture_file_structs)
|
||||
delete texture_file_struct;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<HashType> hashes;
|
||||
for (auto* texture_file_struct : texture_file_structs) {
|
||||
const auto hash = texture_file_struct->crc_hash;
|
||||
if (hash && std::ranges::find(hashes, hash) == hashes.end()) {
|
||||
hashes.push_back(hash);
|
||||
loaded_size += texture_file_struct->data.size();
|
||||
if (current_client) {
|
||||
current_client->EnqueueAdd(hash, std::move(texture_file_struct->data));
|
||||
}
|
||||
}
|
||||
delete texture_file_struct;
|
||||
}
|
||||
|
||||
auto hashes = IngestModfile(texture_file_structs, &loaded_size);
|
||||
if (!hashes.empty()) {
|
||||
loaded_files.emplace(modfiles[i], std::move(hashes));
|
||||
loaded_files.push_back({modfiles[i], std::move(hashes)});
|
||||
}
|
||||
}
|
||||
Info("LoadStartupModlists: %llu bytes (%llu MB)\n", loaded_size, loaded_size / 1024 / 1024);
|
||||
@@ -421,26 +652,13 @@ void TextureClient::Initialize()
|
||||
const auto t1 = std::chrono::high_resolution_clock::now();
|
||||
Info("Initialize: begin\n");
|
||||
|
||||
// now load files that were added by AddFile() before the device existed
|
||||
std::vector<std::filesystem::path> pre_existing_paths;
|
||||
{
|
||||
std::lock_guard lk(global_mutex);
|
||||
pre_existing_paths.reserve(loaded_files.size());
|
||||
for (const auto& key : loaded_files | std::views::keys) pre_existing_paths.push_back(key);
|
||||
}
|
||||
for (const auto& path : pre_existing_paths) {
|
||||
// AddFile() before the device existed recorded files but couldn't enqueue them
|
||||
// (no client yet); enqueue them now.
|
||||
for (const auto& path : GetFiles()) {
|
||||
if (!std::filesystem::exists(path)) continue;
|
||||
const auto file_size = std::filesystem::file_size(path);
|
||||
auto texture_file_structs = ProcessModfile(path, file_size > 400'000'000);
|
||||
std::vector<HashType> seen;
|
||||
for (auto* texture_file_struct : texture_file_structs) {
|
||||
const auto hash = texture_file_struct->crc_hash;
|
||||
if (hash && std::ranges::find(seen, hash) == seen.end()) {
|
||||
seen.push_back(hash);
|
||||
EnqueueAdd(hash, std::move(texture_file_struct->data));
|
||||
}
|
||||
delete texture_file_struct;
|
||||
}
|
||||
IngestModfile(texture_file_structs);
|
||||
}
|
||||
|
||||
LoadStartupModlists();
|
||||
@@ -449,125 +667,3 @@ void TextureClient::Initialize()
|
||||
const auto ms = duration_cast<std::chrono::milliseconds>(t2 - t1);
|
||||
Info("Initialize: end, took %d ms\n", ms);
|
||||
}
|
||||
|
||||
int TextureClient::AddTexture(uModTexturePtr auto pTexture)
|
||||
{
|
||||
if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DTexture9*>) {
|
||||
SetLastCreatedTexture(nullptr);
|
||||
}
|
||||
else if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DVolumeTexture9*>) {
|
||||
SetLastCreatedVolumeTexture(nullptr);
|
||||
}
|
||||
else if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DCubeTexture9*>) {
|
||||
SetLastCreatedCubeTexture(nullptr);
|
||||
}
|
||||
|
||||
if (pTexture->FAKE) {
|
||||
return RETURN_OK; // this is a fake texture
|
||||
}
|
||||
|
||||
if (gl_ErrorState & uMod_ERROR_FATAL) {
|
||||
return RETURN_FATAL_ERROR;
|
||||
}
|
||||
|
||||
Message("TextureClient::AddTexture( Cube: %p): %p (thread: %u)\n", pTexture, this, GetCurrentThreadId());
|
||||
|
||||
pTexture->Hash = pTexture->GetHash();
|
||||
if (!pTexture->Hash) {
|
||||
return RETURN_FATAL_ERROR;
|
||||
}
|
||||
|
||||
if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DTexture9*>) {
|
||||
OriginalTextures.push_back(pTexture);
|
||||
}
|
||||
else if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DVolumeTexture9*>) {
|
||||
OriginalVolumeTextures.push_back(pTexture);
|
||||
}
|
||||
else if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DCubeTexture9*>) {
|
||||
OriginalCubeTextures.push_back(pTexture);
|
||||
}
|
||||
|
||||
return LookUpToMod(pTexture); // check if this texture should be modded
|
||||
}
|
||||
|
||||
int TextureClient::RemoveTexture(uModTexturePtr auto pTexture)
|
||||
{
|
||||
Message("TextureClient::RemoveTexture( %p, %#lX): %p\n", pTexture, pTexture->Hash, this);
|
||||
|
||||
if (gl_ErrorState & uMod_ERROR_FATAL) {
|
||||
return RETURN_FATAL_ERROR;
|
||||
}
|
||||
|
||||
if (!pTexture->FAKE) {
|
||||
if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DTexture9*>) {
|
||||
utils::erase_first(OriginalTextures, pTexture);
|
||||
}
|
||||
else if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DVolumeTexture9*>) {
|
||||
utils::erase_first(OriginalVolumeTextures, pTexture);
|
||||
}
|
||||
else if constexpr (std::same_as<decltype(pTexture), uMod_IDirect3DCubeTexture9*>) {
|
||||
utils::erase_first(OriginalCubeTextures, pTexture);
|
||||
}
|
||||
}
|
||||
if (!pTexture->Reference)
|
||||
return RETURN_OK; // Should this ever happen?
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
int TextureClient::LookUpToMod(uModTexturePtr auto pTexture)
|
||||
{
|
||||
Message("TextureClient::LookUpToMod( %p): hash: %#lX\n", pTexture, pTexture->Hash);
|
||||
int ret = RETURN_OK;
|
||||
|
||||
if (pTexture->CrossRef_D3Dtex != nullptr)
|
||||
return ret; // bug, this texture is already switched
|
||||
|
||||
auto found = modded_textures.find(pTexture->Hash.crc32);
|
||||
if (found == modded_textures.end())
|
||||
if (found = modded_textures.find(pTexture->Hash.crc64), !pTexture->Hash.crc64 || found == modded_textures.end())
|
||||
return ret;
|
||||
|
||||
const auto textureFileStruct = found->second;
|
||||
|
||||
decltype(pTexture) fake_texture;
|
||||
ret = LoadTexture(textureFileStruct, &fake_texture);
|
||||
if (ret != RETURN_OK)
|
||||
return ret;
|
||||
|
||||
ret = SwitchTextures(fake_texture, pTexture);
|
||||
if (ret != RETURN_OK) {
|
||||
Message("TextureClient::LookUpToMod(): textures not switched %#lX\n", textureFileStruct->crc_hash);
|
||||
fake_texture->Release();
|
||||
return ret;
|
||||
}
|
||||
fake_texture->Reference = textureFileStruct;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int TextureClient::LoadTexture(TextureFileStruct* file_in_memory, uModTexturePtrPtr auto ppTexture)
|
||||
{
|
||||
Message("LoadTexture( %p, %p, %#lX): %p\n", file_in_memory, ppTexture, file_in_memory->crc_hash, this);
|
||||
if (const auto ret = DirectX::CreateDDSTextureFromMemoryEx(
|
||||
D3D9Device,
|
||||
file_in_memory->data.data(),
|
||||
file_in_memory->data.size(),
|
||||
0, D3DPOOL_MANAGED, false,
|
||||
reinterpret_cast<LPDIRECT3DTEXTURE9*>(ppTexture)); ret != D3D_OK) {
|
||||
*ppTexture = nullptr;
|
||||
Warning("LoadDDSTexture (%p, %#lX): FAILED ret: \n", file_in_memory->data.data(), file_in_memory->crc_hash, ret);
|
||||
return RETURN_TEXTURE_NOT_LOADED;
|
||||
}
|
||||
if constexpr (std::same_as<decltype(ppTexture), uMod_IDirect3DTexture9**>) {
|
||||
SetLastCreatedTexture(nullptr);
|
||||
}
|
||||
else if constexpr (std::same_as<decltype(ppTexture), uMod_IDirect3DVolumeTexture9**>) {
|
||||
SetLastCreatedVolumeTexture(nullptr);
|
||||
}
|
||||
else if constexpr (std::same_as<decltype(ppTexture), uMod_IDirect3DCubeTexture9**>) {
|
||||
SetLastCreatedCubeTexture(nullptr);
|
||||
}
|
||||
(*ppTexture)->FAKE = true;
|
||||
|
||||
Message("LoadTexture (%p, %#lX): DONE\n", *ppTexture, file_in_memory->crc_hash);
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
+57
-93
@@ -6,45 +6,7 @@ module;
|
||||
|
||||
export module TextureFunction;
|
||||
|
||||
export template <typename T>
|
||||
concept uModTexturePtr = requires(T a)
|
||||
{
|
||||
std::same_as<uMod_IDirect3DTexture9*, T> ||
|
||||
std::same_as<uMod_IDirect3DVolumeTexture9*, T> ||
|
||||
std::same_as<uMod_IDirect3DCubeTexture9*, T>;
|
||||
};
|
||||
|
||||
export template <typename T>
|
||||
concept uModTexturePtrPtr = uModTexturePtr<std::remove_pointer_t<T>>;
|
||||
|
||||
export template <typename T> requires uModTexturePtr<T>
|
||||
void UnswitchTextures(T pTexture)
|
||||
{
|
||||
decltype(pTexture) CrossRef = pTexture->CrossRef_D3Dtex;
|
||||
if (CrossRef != nullptr) {
|
||||
std::swap(pTexture->m_D3Dtex, CrossRef->m_D3Dtex);
|
||||
|
||||
// cancel the link
|
||||
CrossRef->CrossRef_D3Dtex = nullptr;
|
||||
pTexture->CrossRef_D3Dtex = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
export template <typename T> requires uModTexturePtr<T>
|
||||
int SwitchTextures(T pTexture1, T pTexture2)
|
||||
{
|
||||
if (pTexture1->m_D3Ddev == pTexture2->m_D3Ddev && pTexture1->CrossRef_D3Dtex == nullptr && pTexture2->CrossRef_D3Dtex == nullptr) {
|
||||
// make cross reference
|
||||
pTexture1->CrossRef_D3Dtex = pTexture2;
|
||||
pTexture2->CrossRef_D3Dtex = pTexture1;
|
||||
|
||||
// switch textures
|
||||
std::swap(pTexture1->m_D3Dtex, pTexture2->m_D3Dtex);
|
||||
return RETURN_OK;
|
||||
}
|
||||
return RETURN_TEXTURE_NOT_SWITCHED;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
constexpr auto crctab64 = std::to_array({
|
||||
0x0000000000000000ULL, 0x7ad870c830358979ULL, 0xf5b0e190606b12f2ULL,
|
||||
0x8f689158505e9b8bULL, 0xc038e5739841b68fULL, 0xbae095bba8743ff6ULL,
|
||||
@@ -133,10 +95,12 @@ constexpr auto crctab64 = std::to_array({
|
||||
0xa6df411fbfb21ca3ULL, 0xdc0731d78f8795daULL, 0x536fa08fdfd90e51ULL,
|
||||
0x29b7d047efec8728ULL
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
export namespace TextureFunction {
|
||||
|
||||
uint64_t get_crc64(const char* data, unsigned int length) {
|
||||
uint64_t get_crc64(const char* data, unsigned int length)
|
||||
{
|
||||
uint64_t crc = 0xFFFFFFFFFFFFFFFFULL;
|
||||
|
||||
while (length--) {
|
||||
@@ -162,7 +126,7 @@ export namespace TextureFunction {
|
||||
|
||||
int GetBitsFromFormat(D3DFORMAT format)
|
||||
{
|
||||
switch (format) //switch trough the formats to calculate the size of the raw data
|
||||
switch (format) // switch trough the formats to calculate the size of the raw data
|
||||
{
|
||||
case D3DFMT_A1: // 1-bit monochrome.
|
||||
{
|
||||
@@ -170,75 +134,75 @@ export namespace TextureFunction {
|
||||
}
|
||||
|
||||
case D3DFMT_R3G3B2: // 8-bit RGB texture format using 3 bits for red, 3 bits for green, and 2 bits for blue.
|
||||
case D3DFMT_A8: // 8-bit alpha only.
|
||||
case D3DFMT_A8P8: // 8-bit color indexed with 8 bits of alpha.
|
||||
case D3DFMT_P8: // 8-bit color indexed.
|
||||
case D3DFMT_L8: // 8-bit luminance only.
|
||||
case D3DFMT_A4L4: // 8-bit using 4 bits each for alpha and luminance.
|
||||
case D3DFMT_A8: // 8-bit alpha only.
|
||||
case D3DFMT_A8P8: // 8-bit color indexed with 8 bits of alpha.
|
||||
case D3DFMT_P8: // 8-bit color indexed.
|
||||
case D3DFMT_L8: // 8-bit luminance only.
|
||||
case D3DFMT_A4L4: // 8-bit using 4 bits each for alpha and luminance.
|
||||
case D3DFMT_FORCE_DWORD:
|
||||
case D3DFMT_S8_LOCKABLE: // A lockable 8-bit stencil buffer.
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
case D3DFMT_D16_LOCKABLE: //16-bit z-buffer bit depth.
|
||||
case D3DFMT_D15S1: // 16-bit z-buffer bit depth where 15 bits are reserved for the depth channel and 1 bit is reserved for the stencil channel.
|
||||
case D3DFMT_L6V5U5: // 16-bit bump-map format with luminance using 6 bits for luminance, and 5 bits each for v and u.
|
||||
case D3DFMT_V8U8: // 16-bit bump-map format using 8 bits each for u and v data.
|
||||
case D3DFMT_CxV8U8: // 16-bit normal compression format. The texture sampler computes the C channel from: C = sqrt(1 - U2 - V2).
|
||||
case D3DFMT_R5G6B5: // 16-bit RGB pixel format with 5 bits for red, 6 bits for green, and 5 bits for blue.
|
||||
case D3DFMT_X1R5G5B5: // 16-bit pixel format where 5 bits are reserved for each color.
|
||||
case D3DFMT_A1R5G5B5: // 16-bit pixel format where 5 bits are reserved for each color and 1 bit is reserved for alpha.
|
||||
case D3DFMT_A4R4G4B4: // 16-bit ARGB pixel format with 4 bits for each channel.
|
||||
case D3DFMT_A8R3G3B2: // 16-bit ARGB texture format using 8 bits for alpha, 3 bits each for red and green, and 2 bits for blue.
|
||||
case D3DFMT_X4R4G4B4: // 16-bit RGB pixel format using 4 bits for each color.
|
||||
case D3DFMT_L16: // 16-bit luminance only.
|
||||
case D3DFMT_R16F: // 16-bit float format using 16 bits for the red channel.
|
||||
case D3DFMT_A8L8: // 16-bit using 8 bits each for alpha and luminance.
|
||||
case D3DFMT_D16: // 16-bit z-buffer bit depth.
|
||||
case D3DFMT_INDEX16: // 16-bit index buffer bit depth.
|
||||
case D3DFMT_G8R8_G8B8: // ??
|
||||
case D3DFMT_R8G8_B8G8: // ??
|
||||
case D3DFMT_UYVY: // ??
|
||||
case D3DFMT_YUY2: // ??
|
||||
case D3DFMT_D16_LOCKABLE: // 16-bit z-buffer bit depth.
|
||||
case D3DFMT_D15S1: // 16-bit z-buffer bit depth where 15 bits are reserved for the depth channel and 1 bit is reserved for the stencil channel.
|
||||
case D3DFMT_L6V5U5: // 16-bit bump-map format with luminance using 6 bits for luminance, and 5 bits each for v and u.
|
||||
case D3DFMT_V8U8: // 16-bit bump-map format using 8 bits each for u and v data.
|
||||
case D3DFMT_CxV8U8: // 16-bit normal compression format. The texture sampler computes the C channel from: C = sqrt(1 - U2 - V2).
|
||||
case D3DFMT_R5G6B5: // 16-bit RGB pixel format with 5 bits for red, 6 bits for green, and 5 bits for blue.
|
||||
case D3DFMT_X1R5G5B5: // 16-bit pixel format where 5 bits are reserved for each color.
|
||||
case D3DFMT_A1R5G5B5: // 16-bit pixel format where 5 bits are reserved for each color and 1 bit is reserved for alpha.
|
||||
case D3DFMT_A4R4G4B4: // 16-bit ARGB pixel format with 4 bits for each channel.
|
||||
case D3DFMT_A8R3G3B2: // 16-bit ARGB texture format using 8 bits for alpha, 3 bits each for red and green, and 2 bits for blue.
|
||||
case D3DFMT_X4R4G4B4: // 16-bit RGB pixel format using 4 bits for each color.
|
||||
case D3DFMT_L16: // 16-bit luminance only.
|
||||
case D3DFMT_R16F: // 16-bit float format using 16 bits for the red channel.
|
||||
case D3DFMT_A8L8: // 16-bit using 8 bits each for alpha and luminance.
|
||||
case D3DFMT_D16: // 16-bit z-buffer bit depth.
|
||||
case D3DFMT_INDEX16: // 16-bit index buffer bit depth.
|
||||
case D3DFMT_G8R8_G8B8: // ??
|
||||
case D3DFMT_R8G8_B8G8: // ??
|
||||
case D3DFMT_UYVY: // ??
|
||||
case D3DFMT_YUY2: // ??
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
|
||||
case D3DFMT_R8G8B8: //24-bit RGB pixel format with 8 bits per channel.
|
||||
case D3DFMT_R8G8B8: // 24-bit RGB pixel format with 8 bits per channel.
|
||||
{
|
||||
return 24;
|
||||
}
|
||||
|
||||
case D3DFMT_R32F: // 32-bit float format using 32 bits for the red channel.
|
||||
case D3DFMT_X8L8V8U8: // 32-bit bump-map format with luminance using 8 bits for each channel.
|
||||
case D3DFMT_A2W10V10U10: // 32-bit bump-map format using 2 bits for alpha and 10 bits each for w, v, and u.
|
||||
case D3DFMT_Q8W8V8U8: // 32-bit bump-map format using 8 bits for each channel.
|
||||
case D3DFMT_V16U16: // 32-bit bump-map format using 16 bits for each channel.
|
||||
case D3DFMT_A8R8G8B8: // 32-bit ARGB pixel format with alpha, using 8 bits per channel.
|
||||
case D3DFMT_X8R8G8B8: // 32-bit RGB pixel format, where 8 bits are reserved for each color.
|
||||
case D3DFMT_A2B10G10R10: // 32-bit pixel format using 10 bits for each color and 2 bits for alpha.
|
||||
case D3DFMT_A8B8G8R8: // 32-bit ARGB pixel format with alpha, using 8 bits per channel.
|
||||
case D3DFMT_X8B8G8R8: // 32-bit RGB pixel format, where 8 bits are reserved for each color.
|
||||
case D3DFMT_G16R16: // 32-bit pixel format using 16 bits each for green and red.
|
||||
case D3DFMT_G16R16F: // 32-bit float format using 16 bits for the red channel and 16 bits for the green channel.
|
||||
case D3DFMT_A2R10G10B10: // 32-bit pixel format using 10 bits each for red, green, and blue, and 2 bits for alpha.
|
||||
case D3DFMT_D32: // 32-bit z-buffer bit depth.
|
||||
case D3DFMT_D24S8: // 32-bit z-buffer bit depth using 24 bits for the depth channel and 8 bits for the stencil channel.
|
||||
case D3DFMT_D24X8: //32-bit z-buffer bit depth using 24 bits for the depth channel.
|
||||
case D3DFMT_D24X4S4: // 32-bit z-buffer bit depth using 24 bits for the depth channel and 4 bits for the stencil channel.
|
||||
case D3DFMT_R32F: // 32-bit float format using 32 bits for the red channel.
|
||||
case D3DFMT_X8L8V8U8: // 32-bit bump-map format with luminance using 8 bits for each channel.
|
||||
case D3DFMT_A2W10V10U10: // 32-bit bump-map format using 2 bits for alpha and 10 bits each for w, v, and u.
|
||||
case D3DFMT_Q8W8V8U8: // 32-bit bump-map format using 8 bits for each channel.
|
||||
case D3DFMT_V16U16: // 32-bit bump-map format using 16 bits for each channel.
|
||||
case D3DFMT_A8R8G8B8: // 32-bit ARGB pixel format with alpha, using 8 bits per channel.
|
||||
case D3DFMT_X8R8G8B8: // 32-bit RGB pixel format, where 8 bits are reserved for each color.
|
||||
case D3DFMT_A2B10G10R10: // 32-bit pixel format using 10 bits for each color and 2 bits for alpha.
|
||||
case D3DFMT_A8B8G8R8: // 32-bit ARGB pixel format with alpha, using 8 bits per channel.
|
||||
case D3DFMT_X8B8G8R8: // 32-bit RGB pixel format, where 8 bits are reserved for each color.
|
||||
case D3DFMT_G16R16: // 32-bit pixel format using 16 bits each for green and red.
|
||||
case D3DFMT_G16R16F: // 32-bit float format using 16 bits for the red channel and 16 bits for the green channel.
|
||||
case D3DFMT_A2R10G10B10: // 32-bit pixel format using 10 bits each for red, green, and blue, and 2 bits for alpha.
|
||||
case D3DFMT_D32: // 32-bit z-buffer bit depth.
|
||||
case D3DFMT_D24S8: // 32-bit z-buffer bit depth using 24 bits for the depth channel and 8 bits for the stencil channel.
|
||||
case D3DFMT_D24X8: // 32-bit z-buffer bit depth using 24 bits for the depth channel.
|
||||
case D3DFMT_D24X4S4: // 32-bit z-buffer bit depth using 24 bits for the depth channel and 4 bits for the stencil channel.
|
||||
case D3DFMT_D32F_LOCKABLE: // A lockable format where the depth value is represented as a standard IEEE floating-point number.
|
||||
case D3DFMT_D24FS8: // A non-lockable format that contains 24 bits of depth (in a 24-bit floating point format - 20e4) and 8 bits of stencil.
|
||||
case D3DFMT_D32_LOCKABLE: // A lockable 32-bit depth buffer.
|
||||
case D3DFMT_INDEX32: // 32-bit index buffer bit depth.
|
||||
case D3DFMT_D24FS8: // A non-lockable format that contains 24 bits of depth (in a 24-bit floating point format - 20e4) and 8 bits of stencil.
|
||||
case D3DFMT_D32_LOCKABLE: // A lockable 32-bit depth buffer.
|
||||
case D3DFMT_INDEX32: // 32-bit index buffer bit depth.
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
case D3DFMT_G32R32F: // 64-bit float format using 32 bits for the red channel and 32 bits for the green channel.
|
||||
case D3DFMT_Q16W16V16U16: // 64-bit bump-map format using 16 bits for each component.
|
||||
case D3DFMT_A16B16G16R16: // 64-bit pixel format using 16 bits for each component.
|
||||
case D3DFMT_G32R32F: // 64-bit float format using 32 bits for the red channel and 32 bits for the green channel.
|
||||
case D3DFMT_Q16W16V16U16: // 64-bit bump-map format using 16 bits for each component.
|
||||
case D3DFMT_A16B16G16R16: // 64-bit pixel format using 16 bits for each component.
|
||||
case D3DFMT_A16B16G16R16F: // 64-bit float format using 16 bits for the each channel (alpha, blue, green, red).
|
||||
{
|
||||
return 64;
|
||||
@@ -257,7 +221,7 @@ export namespace TextureFunction {
|
||||
case D3DFMT_DXT1: {
|
||||
return 4;
|
||||
}
|
||||
default: //compressed formats
|
||||
default: // compressed formats
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
@@ -406,9 +370,9 @@ export namespace TextureFunction {
|
||||
return {};
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef _DEBUG
|
||||
ImageSave(compressed_image, entry);
|
||||
#endif
|
||||
#endif
|
||||
return dds_blob;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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};
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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};
|
||||
}
|
||||
@@ -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};
|
||||
}
|
||||
Reference in New Issue
Block a user