1.5.6, severely improve memory footprint and loading speed (#13)

* remove more unnecessary code

* todo?

* 1.5.5.0

* change GetHash from in_out parameter to return the hash

* remove ForceReload bool for textures

* remove textureserver, place logic in textureclient, not yet finished
next up change FileToMod and shit to use modded_textures map

* fix debug compilation errors

* fix typo

* should_update boolean, replace the entire MergeUpdate logic later

* tidy up d3d9_dll.cpp and bits (#12)

* define `ASSERT`
Added minhook lib to tidy up hooks
Remove cruft from dx9_dll.cpp

* Bug fix

* Another typo

---------

Co-authored-by: Jon <>

* gitignore

* Proxy functions, cache dx9 device type

* simplify LoadModsFromFile

* move minhook dependency to fetch content

* Make it work

* Tweaked debug for file reads

* Fixed inverse check

* unordered_map

* set should_update (yikes)

* simplify libzippp.cmake

* remove unnecessary code

* rename project files (keep uMod_ prefix only for d3d9 classes)

* remove unused Nothing() function

* remove unnecessary fields

* remove some code duplication

refactor methods together

* refactor SwitchTextures and UnswitchTextures together

* move loaded_size into function

* enable libzippp encryption again

* copy data from opened zipentry and then delete the entry

* fix hash bug in volume textures

* const

* change uMod_TextureClient to TextureClient

* revert libzippp.cmake

* 1.5.6
This commit is contained in:
DubbleClick
2023-11-22 21:50:11 +01:00
committed by GitHub
parent 13b7df3ae3
commit f07e180b53
44 changed files with 919 additions and 2562 deletions
+15
View File
@@ -0,0 +1,15 @@
#pragma once
//#define HashType DWORD64
using HashType = DWORD32;
#ifdef LOG_MESSAGE
#include <iostream>
#ifdef _DEBUG
#define Message(...) { printf(__VA_ARGS__); }
#else
#define Message(...)
#endif
#endif
+8
View File
@@ -42,3 +42,11 @@
#define uMod_ERROR_UPDATE 1u<<7
#define uMod_ERROR_SERVER 1u<<8
__declspec(noreturn) void FatalAssert(
const char* expr,
const char* file,
unsigned int line,
const char* function);
#define ASSERT(expr) ((void)(!!(expr) || (FatalAssert(#expr, __FILE__, (unsigned)__LINE__, __FUNCTION__), 0)))
@@ -9,11 +9,10 @@ struct TpfEntry {
std::string name;
std::string entry;
uint32_t crc_hash;
void* data;
unsigned long long size;
std::vector<char> data;
};
class gMod_FileLoader {
class FileLoader {
std::string file_name;
const std::string TPF_PASSWORD{
0x73, 0x2A, 0x63, 0x7D, 0x5F, 0x0A, static_cast<char>(0xA6), static_cast<char>(0xBD),
@@ -25,7 +24,7 @@ class gMod_FileLoader {
};
public:
gMod_FileLoader(const std::string& fileName);
FileLoader(const std::string& fileName);
std::vector<TpfEntry> GetContents();
+8 -8
View File
@@ -4,15 +4,16 @@
#include <cstdlib>
#include <cstdio>
#include "Utils.h"
#include <d3d9.h>
#include <d3dx9.h>
#include "uMod_GlobalDefines.h"
#include "uMod_Error.h"
#include "uMod_Defines.h"
#include "uMod_DX9_dll.h"
#include "uMod_TextureFunction.h"
#include "Defines.h"
#include "Error.h"
#include "Defines.h"
#include "dll_main.h"
#include "TextureFunction.h"
#include "uMod_IDirect3D9.h"
#include "uMod_IDirect3D9Ex.h"
@@ -24,10 +25,9 @@
#include "uMod_IDirect3DTexture9.h"
#include "uMod_IDirect3DVolumeTexture9.h"
#include "uMod_ArrayHandler.h"
#include "uMod_TextureServer.h"
#include "uMod_TextureClient.h"
#include "TextureClient.h"
#pragma warning(disable : 4477)
extern unsigned int gl_ErrorState;
extern HINSTANCE gl_hThisInstance;
+251
View File
@@ -0,0 +1,251 @@
#pragma once
#include <map>
#include "FileLoader.h"
#include "uMod_IDirect3DTexture9.h"
extern unsigned int gl_ErrorState;
struct TextureFileStruct {
std::vector<char> data{};
HashType crc_hash = 0; // hash value
};
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>;
};
template <typename T>
concept uModTexturePtrPtr = uModTexturePtr<std::remove_pointer_t<T>>;
/*
* An object of this class is owned by each d3d9 device.
* functions called by the Server are called from the server thread instance.
* All other functions are called from the render thread instance of the game itself.
*/
class TextureClient {
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(...)
int MergeUpdate(); //called from uMod_IDirect3DDevice9::BeginScene()
// Add TpfEntry data, return size of data added. 0 on failure.
unsigned long AddFile(TpfEntry& entry);
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
D3DCOLOR FontColour;
D3DCOLOR TextureColour;
void Initialize();
private:
IDirect3DDevice9* D3D9Device;
// Cached info about whether this id a dx9ex device or not; used for proxy functions
bool isDirectXExDevice = false;
// DX9 proxy functions
uMod_IDirect3DTexture9* GetSingleTexture();
uMod_IDirect3DVolumeTexture9* GetSingleVolumeTexture();
uMod_IDirect3DCubeTexture9* GetSingleCubeTexture();
int SetLastCreatedTexture(uMod_IDirect3DTexture9*);
int SetLastCreatedVolumeTexture(uMod_IDirect3DVolumeTexture9*);
int SetLastCreatedCubeTexture(uMod_IDirect3DCubeTexture9*);
bool should_update = false;
int LockMutex();
int UnlockMutex();
HANDLE Mutex;
std::unordered_map<HashType, 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);
void LoadModsFromFile(const char* source);
};
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, %p\n", pTexture, pTexture->Hash, this);
int ret = RETURN_OK;
if (pTexture->CrossRef_D3Dtex != nullptr)
return ret; // bug, this texture is already switched
const auto found = modded_textures.find(pTexture->Hash);
if (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 constexpr (std::same_as<decltype(ppTexture), uMod_IDirect3DTexture9**>) {
if (D3D_OK != D3DXCreateTextureFromFileInMemoryEx(
D3D9Device, file_in_memory->data.data(),
file_in_memory->data.size(), D3DX_DEFAULT, D3DX_DEFAULT,
D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED,
D3DX_DEFAULT, D3DX_DEFAULT, 0, nullptr, nullptr,
(IDirect3DTexture9**)ppTexture)) {
*ppTexture = nullptr;
return RETURN_TEXTURE_NOT_LOADED;
}
SetLastCreatedTexture(nullptr);
}
else if constexpr (std::same_as<decltype(ppTexture), uMod_IDirect3DVolumeTexture9**>) {
if (D3D_OK != D3DXCreateVolumeTextureFromFileInMemoryEx(
D3D9Device, file_in_memory->data.data(),
file_in_memory->data.size(), D3DX_DEFAULT, D3DX_DEFAULT,
D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0,
nullptr,
nullptr,
(IDirect3DVolumeTexture9**)ppTexture)) {
*ppTexture = nullptr;
return RETURN_TEXTURE_NOT_LOADED;
}
SetLastCreatedVolumeTexture(nullptr);
}
else if constexpr (std::same_as<decltype(ppTexture), uMod_IDirect3DCubeTexture9**>) {
if (D3D_OK != D3DXCreateCubeTextureFromFileInMemoryEx(
D3D9Device, file_in_memory->data.data(), file_in_memory->data.size(), D3DX_DEFAULT, D3DX_DEFAULT, 0,
D3DFMT_UNKNOWN, D3DPOOL_MANAGED,
D3DX_DEFAULT, D3DX_DEFAULT, 0, nullptr, nullptr,
(IDirect3DCubeTexture9**)ppTexture)) {
*ppTexture = nullptr;
return RETURN_TEXTURE_NOT_LOADED;
}
SetLastCreatedCubeTexture(nullptr);
}
(*ppTexture)->FAKE = true;
Message("LoadTexture( %p, %#lX): DONE\n", *ppTexture, file_in_memory->crc_hash);
return RETURN_OK;
}
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;
}
}
template<typename T> requires uModTexturePtr<T>
inline 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;
}
@@ -1,6 +1,20 @@
#pragma once
unsigned int GetCRC32(char* pcDatabuf, unsigned int ulDatalen);
constexpr auto crc32_poly = 0xEDB88320u;
constexpr auto ul_crc_in = 0xffffffff;
inline unsigned int GetCRC32(char* pcDatabuf, unsigned int ulDatalen)
{
unsigned int crc = ul_crc_in;
for (unsigned int idx = 0u; idx < ulDatalen; idx++) {
unsigned int data = *pcDatabuf++;
for (unsigned int bit = 0u; bit < 8u; bit++, data >>= 1) {
crc = crc >> 1 ^ ((crc ^ data) & 1 ? crc32_poly : 0);
}
}
return crc;
}
/*
case D3DFMT_MULTI2_ARGB8:
case D3DFMT_VERTEXDATA:
@@ -3,9 +3,9 @@
#include <fstream>
#include <vector>
class XorStreamReader {
class TpfReader {
public:
XorStreamReader(const std::string& path)
TpfReader(const std::string& path)
{
file_stream = std::ifstream(path, std::ios::binary);
if (!file_stream.seekg(0, std::ios::end).good() || !file_stream.seekg(0, std::ios::beg).good()) {
@@ -13,7 +13,7 @@ public:
}
}
~XorStreamReader()
~TpfReader()
{
file_stream.close();
}
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include <vector>
namespace utils
{
template<typename T>
void erase_first(std::vector<T>& vec, const T& elem)
{
const auto found = std::ranges::find(vec, elem);
if (found != std::ranges::end(vec)) {
vec.erase(found);
}
}
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <d3d9.h>
void InitInstance(HINSTANCE hModule);
void ExitInstance();
HMODULE LoadOriginalDll();
IDirect3D9* APIENTRY uMod_Direct3DCreate9(UINT SDKVersion);
HRESULT APIENTRY uMod_Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex** ppD3D);
-165
View File
@@ -1,165 +0,0 @@
#pragma once
#include "uMod_GlobalDefines.h"
#include "uMod_IDirect3DTexture9.h"
extern unsigned int gl_ErrorState;
struct TextureFileStruct {
bool ForceReload; // to force a reload of the texture (if it is already modded)
char* pData; // store texture file as file in memory
unsigned int Size; // size of file
int NumberOfTextures;
int Reference; // for a fast delete in the FileHandler
IDirect3DBaseTexture9** Textures; // pointer to the fake textures
MyTypeHash Hash; // hash value
};
class uMod_FileHandler // array to store TextureFileStruct
{
public:
uMod_FileHandler();
~uMod_FileHandler();
int Add(TextureFileStruct* file);
int Remove(TextureFileStruct* file);
int GetNumber() { return Number; }
TextureFileStruct* operator [](int i)
{
if (i < 0 || i >= Number) {
return nullptr;
}
return Files[i / FieldLength][i % FieldLength];
}
protected:
static constexpr int FieldLength = 1024;
long Number = 0;
int FieldCounter = 0;
TextureFileStruct*** Files = nullptr;
};
template <class T>
class uMod_TextureHandler // array to store uMod_IDirect3DTexture9, uMod_IDirect3DVolumeTexture9 or uMod_IDirect3DCubeTexture9
{
public:
uMod_TextureHandler();
~uMod_TextureHandler();
int Add(T* texture);
int Remove(T* texture);
int GetNumber() { return Number; }
T* operator [](int i)
{
if (i < 0 || i >= Number) {
return nullptr;
}
return Textures[i / FieldLength][i % FieldLength];
}
private:
static constexpr int FieldLength = 1024;
long Number;
int FieldCounter;
T*** Textures;
};
template <class T>
uMod_TextureHandler<T>::uMod_TextureHandler()
{
Message("uMod_TextureHandler(): %p\n", this);
Number = 0;
FieldCounter = 0;
Textures = NULL;
}
template <class T>
uMod_TextureHandler<T>::~uMod_TextureHandler()
{
Message("~uMod_TextureHandler(): %p\n", this);
if (Textures != nullptr) {
for (int i = 0; i < FieldCounter; i++) {
delete [] Textures[i];
}
delete [] Textures;
}
}
template <class T>
int uMod_TextureHandler<T>::Add(T* pTexture)
{
Message("uMod_TextureHandler::Add( %p): %p\n", pTexture, this);
if (gl_ErrorState & uMod_ERROR_FATAL) {
return RETURN_FATAL_ERROR;
}
if (pTexture->Reference >= 0) {
return RETURN_TEXTURE_ALLREADY_ADDED;
}
if (Number / FieldLength == FieldCounter) {
T*** temp = nullptr;
try { temp = new T**[FieldCounter + 10]; }
catch (...) {
gl_ErrorState |= uMod_ERROR_MEMORY | uMod_ERROR_TEXTURE;
return RETURN_NO_MEMORY;
}
for (int i = 0; i < FieldCounter; i++) {
temp[i] = Textures[i];
}
for (int i = FieldCounter; i < FieldCounter + 10; i++) {
temp[i] = NULL;
}
FieldCounter += 10;
delete [] Textures;
Textures = temp;
}
if (Number % FieldLength == 0) {
try {
if (Textures[Number / FieldLength] == NULL) {
Textures[Number / FieldLength] = new T*[FieldLength];
}
}
catch (...) {
Textures[Number / FieldLength] = NULL;
gl_ErrorState |= uMod_ERROR_MEMORY | uMod_ERROR_TEXTURE;
return RETURN_NO_MEMORY;
}
}
Textures[Number / FieldLength][Number % FieldLength] = pTexture;
pTexture->Reference = Number++;
return RETURN_OK;
}
template <class T>
int uMod_TextureHandler<T>::Remove(T* pTexture) //will be called, if a texture is completely released
{
Message("uMod_TextureHandler::Remove(%p): %p\n", pTexture, this);
if (gl_ErrorState & uMod_ERROR_FATAL) {
return RETURN_FATAL_ERROR;
}
int ref = pTexture->Reference;
if (ref < 0) {
return RETURN_OK; // returning if no TextureHandlerRef is set
}
if (ref < (--Number)) {
Textures[ref / FieldLength][ref % FieldLength] = Textures[Number / FieldLength][Number % FieldLength];
Textures[ref / FieldLength][ref % FieldLength]->Reference = ref;
}
return RETURN_OK;
}
-21
View File
@@ -1,21 +0,0 @@
#pragma once
#include <d3d9.h>
void InitInstance(HINSTANCE hModule);
void ExitInstance();
void LoadOriginalDll();
bool FindLoadedDll();
bool IsDesiredModule(HMODULE hModule, HANDLE hProcess);
bool HasDesiredMethods(HMODULE hModule, HANDLE hProcess);
bool HookThisProgram(char* ret);
void* DetourFunc(BYTE* src, const BYTE* dst, int len);
bool RetourFunc(BYTE* src, BYTE* restore, int len);
IDirect3D9*APIENTRY uMod_Direct3DCreate9(UINT SDKVersion);
HRESULT APIENTRY uMod_Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex** ppD3D);
#ifdef DIRECT_INJECTION
void Nothing();
#endif
-50
View File
@@ -1,50 +0,0 @@
#pragma once
#include <iostream>
#ifdef LOG_MESSAGE
extern FILE* gl_File;
#ifdef _DEBUG
#define Message(...) { printf(__VA_ARGS__); }
#else
#define Message(...)
#endif
#ifdef HOOK_INJECTION
#define OpenMessage(...) {if (fopen_s( &gl_File, "uMod_log.txt", "wt")) gl_File=NULL; else fprintf( gl_File, "HI R40: 0000000\n");}
#endif
#ifdef DIRECT_INJECTION
#define OpenMessage(...)
#endif
#ifdef NO_INJECTION
#define OpenMessage(...) {if (fopen_s( &gl_File, "uMod_log.txt", "wt")) gl_File=NULL; else fprintf( gl_File, "NI R40: 0000000\n");}
#endif
#define CloseMessage(...)
#else
#define OpenMessage(...)
#define Message(...)
#define CloseMessage(...)
#endif
#ifdef __CDT_PARSER__
typedef unsigned long DWORD64;
typedef unsigned long DWORD32;
#define STDMETHOD(method) virtual HRESULT method
#define STDMETHOD_(ret, method) virtual ret method
#define sprintf_s(...)
#define fprintf(...)
#define fclose(...)
#define fseek(...)
#define ftell(...) 0
#define fflush(...)
typedef LONG HRESULT;
#define UNREFERENCED_PARAMETER(...)
#endif
-45
View File
@@ -1,45 +0,0 @@
#pragma once
//#define MyTypeHash DWORD64
#define MyTypeHash DWORD32
#define BIG_BUFSIZE 1<<24
#define SMALL_BUFSIZE 1<<10
using MsgStruct = struct {
unsigned int Control;
unsigned int Value;
MyTypeHash Hash;
};
using PipeStruct = struct {
HANDLE In;
HANDLE Out;
};
#define uMod_APP_DX9 L"uMod_DX9.txt"
#define uMod_APP_DIR L"uMod"
#define uMod_VERSION L"uMod V 1.0"
#define PIPE_uMod2Game L"\\\\.\\pipe\\uMod2Game"
#define PIPE_Game2uMod L"\\\\.\\pipe\\Game2uMod"
#define CONTROL_ADD_TEXTURE 1
#define CONTROL_FORCE_RELOAD_TEXTURE 2
#define CONTROL_REMOVE_TEXTURE 3
#define CONTROL_FORCE_RELOAD_TEXTURE_DATA 4
#define CONTROL_ADD_TEXTURE_DATA 5
#define CONTROL_MORE_TEXTURES 6
#define CONTROL_SAVE_ALL 10
#define CONTROL_SAVE_SINGLE 11
#define CONTROL_SET_DIR 12
#define CONTROL_KEY_BACK 20
#define CONTROL_KEY_SAVE 21
#define CONTROL_KEY_NEXT 22
#define CONTROL_FONT_COLOUR 30
#define CONTROL_TEXTURE_COLOUR 31
+1 -3
View File
@@ -1,11 +1,10 @@
#pragma once
#include <d3d9.h>
#include "uMod_TextureServer.h"
class uMod_IDirect3D9 : public IDirect3D9 {
public:
uMod_IDirect3D9(IDirect3D9* pOriginal, uMod_TextureServer* server);
uMod_IDirect3D9(IDirect3D9* pOriginal);
virtual ~uMod_IDirect3D9();
// The original DX9 function definitions
@@ -29,5 +28,4 @@ public:
private:
IDirect3D9* m_pIDirect3D9;
uMod_TextureServer* uMod_Server;
};
+1 -3
View File
@@ -1,11 +1,10 @@
#pragma once
#include <d3d9.h>
#include "uMod_TextureServer.h"
class uMod_IDirect3D9Ex : public IDirect3D9Ex {
public:
uMod_IDirect3D9Ex(IDirect3D9Ex* pOriginal, uMod_TextureServer* server);
uMod_IDirect3D9Ex(IDirect3D9Ex* pOriginal);
virtual ~uMod_IDirect3D9Ex();
// The original DX9 function definitions
@@ -36,6 +35,5 @@ public:
private:
IDirect3D9Ex* m_pIDirect3D9Ex;
uMod_TextureServer* uMod_Server;
};
+7 -43
View File
@@ -11,18 +11,15 @@ interface uMod_IDirect3DCubeTexture9 : IDirect3DCubeTexture9 {
// fake texture: store the pointer to the original uMod_IDirect3DCubeTexture9 object, needed if a fake texture is unselected
// original texture: stores the pointer to the fake texture object, is needed if original texture is deleted,
// thus the fake texture can also be deleted
Reference = -1; //need for fast deleting
Hash = 0u;
FAKE = false;
}
// callback interface
IDirect3DCubeTexture9* m_D3Dtex;
uMod_IDirect3DCubeTexture9* CrossRef_D3Dtex;
IDirect3DDevice9* m_D3Ddev;
int Reference;
MyTypeHash Hash;
bool FAKE;
IDirect3DCubeTexture9* m_D3Dtex = nullptr;
uMod_IDirect3DCubeTexture9* CrossRef_D3Dtex = nullptr;
IDirect3DDevice9* m_D3Ddev = nullptr;
TextureFileStruct* Reference = nullptr;
HashType Hash = 0u;
bool FAKE = false;
// original interface
STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj) override;
@@ -50,38 +47,5 @@ interface uMod_IDirect3DCubeTexture9 : IDirect3DCubeTexture9 {
STDMETHOD(UnlockRect)(D3DCUBEMAP_FACES FaceType, UINT Level) override;
int GetHash(MyTypeHash& hash);
[[nodiscard]] HashType GetHash() const;
};
inline void UnswitchTextures(uMod_IDirect3DCubeTexture9* pTexture)
{
uMod_IDirect3DCubeTexture9* CrossRef = pTexture->CrossRef_D3Dtex;
if (CrossRef != nullptr) {
// switch textures back
IDirect3DCubeTexture9* cpy = pTexture->m_D3Dtex;
pTexture->m_D3Dtex = CrossRef->m_D3Dtex;
CrossRef->m_D3Dtex = cpy;
// cancel the link
CrossRef->CrossRef_D3Dtex = nullptr;
pTexture->CrossRef_D3Dtex = nullptr;
}
}
inline int SwitchTextures(uMod_IDirect3DCubeTexture9* pTexture1, uMod_IDirect3DCubeTexture9* 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
IDirect3DCubeTexture9* cpy = pTexture2->m_D3Dtex;
pTexture2->m_D3Dtex = pTexture1->m_D3Dtex;
pTexture1->m_D3Dtex = cpy;
return RETURN_OK;
}
return RETURN_TEXTURE_NOT_SWITCHED;
}
+11 -13
View File
@@ -5,11 +5,12 @@
#include "uMod_IDirect3DTexture9.h"
#include "uMod_IDirect3DVolumeTexture9.h"
#include "uMod_IDirect3DCubeTexture9.h"
#include "TextureClient.h"
class uMod_IDirect3DDevice9 : public IDirect3DDevice9 {
public:
uMod_IDirect3DDevice9(IDirect3DDevice9* pOriginal, uMod_TextureServer* server, int back_buffer_count);
uMod_IDirect3DDevice9(IDirect3DDevice9* pOriginal, int back_buffer_count);
virtual ~uMod_IDirect3DDevice9();
// START: The original DX9 function definitions
@@ -135,9 +136,7 @@ public:
HRESULT __stdcall CreateQuery(D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery) override;
// END: The original DX9 function definitions
uMod_TextureClient* GetuMod_Client() { return uMod_Client; }
TextureClient* GetuMod_Client() { return uMod_Client; }
uMod_IDirect3DTexture9* GetLastCreatedTexture() { return LastCreatedTexture; }
@@ -170,12 +169,12 @@ public:
private:
int CreateSingleTexture();
IDirect3DDevice9* m_pIDirect3DDevice9;
IDirect3DDevice9* m_pIDirect3DDevice9 = nullptr;
int CounterSaveSingleTexture;
uMod_IDirect3DTexture9* SingleTexture;
uMod_IDirect3DVolumeTexture9* SingleVolumeTexture;
uMod_IDirect3DCubeTexture9* SingleCubeTexture;
uMod_IDirect3DTexture9* SingleTexture = nullptr;
uMod_IDirect3DVolumeTexture9* SingleVolumeTexture = nullptr;
uMod_IDirect3DCubeTexture9* SingleCubeTexture = nullptr;
char SingleTextureMod;
D3DCOLOR TextureColour;
@@ -186,10 +185,9 @@ private:
int uMod_Reference;
uMod_IDirect3DTexture9* LastCreatedTexture;
uMod_IDirect3DVolumeTexture9* LastCreatedVolumeTexture;
uMod_IDirect3DCubeTexture9* LastCreatedCubeTexture;
uMod_IDirect3DTexture9* LastCreatedTexture = nullptr;
uMod_IDirect3DVolumeTexture9* LastCreatedVolumeTexture = nullptr;
uMod_IDirect3DCubeTexture9* LastCreatedCubeTexture = nullptr;
uMod_TextureServer* uMod_Server;
uMod_TextureClient* uMod_Client;
TextureClient* uMod_Client;
};
+4 -5
View File
@@ -5,11 +5,12 @@
#include "uMod_IDirect3DTexture9.h"
#include "uMod_IDirect3DVolumeTexture9.h"
#include "uMod_IDirect3DCubeTexture9.h"
#include "TextureClient.h"
class uMod_IDirect3DDevice9Ex : public IDirect3DDevice9Ex {
public:
uMod_IDirect3DDevice9Ex(IDirect3DDevice9Ex* pOriginal, uMod_TextureServer* server, int back_buffer_count);
uMod_IDirect3DDevice9Ex(IDirect3DDevice9Ex* pOriginal, int back_buffer_count);
virtual ~uMod_IDirect3DDevice9Ex();
// START: The original DX9 function definitions
@@ -157,8 +158,7 @@ public:
// END: The original DX9 function definitions
uMod_TextureClient* GetuMod_Client() { return uMod_Client; }
TextureClient* GetuMod_Client() { return uMod_Client; }
uMod_IDirect3DTexture9* GetLastCreatedTexture() { return LastCreatedTexture; }
@@ -211,6 +211,5 @@ private:
uMod_IDirect3DVolumeTexture9* LastCreatedVolumeTexture;
uMod_IDirect3DCubeTexture9* LastCreatedCubeTexture;
uMod_TextureServer* uMod_Server;
uMod_TextureClient* uMod_Client;
TextureClient* uMod_Client;
};
+8 -46
View File
@@ -1,7 +1,7 @@
#pragma once
#include <d3d9.h>
struct TextureFileStruct;
interface uMod_IDirect3DTexture9 : public IDirect3DTexture9 {
uMod_IDirect3DTexture9(IDirect3DTexture9** ppTex, IDirect3DDevice9* pIDirect3DDevice9)
{
@@ -11,18 +11,15 @@ interface uMod_IDirect3DTexture9 : public IDirect3DTexture9 {
// fake texture: store the pointer to the original uMod_IDirect3DTexture9 object, needed if a fake texture is unselected
// original texture: stores the pointer to the fake texture object, is needed if original texture is deleted,
// thus the fake texture can also be deleted
Reference = -1; //need for fast deleting
Hash = 0u;
FAKE = false;
}
// callback interface
IDirect3DTexture9* m_D3Dtex;
uMod_IDirect3DTexture9* CrossRef_D3Dtex;
IDirect3DDevice9* m_D3Ddev;
int Reference;
MyTypeHash Hash;
bool FAKE;
IDirect3DTexture9* m_D3Dtex = nullptr;
uMod_IDirect3DTexture9* CrossRef_D3Dtex = nullptr;
IDirect3DDevice9* m_D3Ddev = nullptr;
TextureFileStruct* Reference = nullptr;
HashType Hash = 0u;
bool FAKE = false;
// original interface
STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj) override;
@@ -48,40 +45,5 @@ interface uMod_IDirect3DTexture9 : public IDirect3DTexture9 {
STDMETHOD(UnlockRect)(UINT Level) override;
STDMETHOD(AddDirtyRect)(CONST RECT* pDirtyRect) override;
int GetHash(MyTypeHash& hash);
[[nodiscard]] HashType GetHash() const;
};
inline void UnswitchTextures(uMod_IDirect3DTexture9* pTexture)
{
uMod_IDirect3DTexture9* CrossRef = pTexture->CrossRef_D3Dtex;
if (CrossRef != nullptr) {
// switch textures back
IDirect3DTexture9* cpy = pTexture->m_D3Dtex;
pTexture->m_D3Dtex = CrossRef->m_D3Dtex;
CrossRef->m_D3Dtex = cpy;
// cancel the link
CrossRef->CrossRef_D3Dtex = nullptr;
pTexture->CrossRef_D3Dtex = nullptr;
}
}
inline int SwitchTextures(uMod_IDirect3DTexture9* pTexture1, uMod_IDirect3DTexture9* 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
IDirect3DTexture9* cpy = pTexture2->m_D3Dtex;
pTexture2->m_D3Dtex = pTexture1->m_D3Dtex;
pTexture1->m_D3Dtex = cpy;
return RETURN_OK;
}
return RETURN_TEXTURE_NOT_SWITCHED;
}
+7 -44
View File
@@ -11,18 +11,15 @@ interface uMod_IDirect3DVolumeTexture9 : IDirect3DVolumeTexture9 {
// fake texture: store the pointer to the original uMod_IDirect3DVolumeTexture9 object, needed if a fake texture is unselected
// original texture: stores the pointer to the fake texture object, is needed if original texture is deleted,
// thus the fake texture can also be deleted
Reference = -1; //need for fast deleting
Hash = 0u;
FAKE = false;
}
// callback interface
IDirect3DVolumeTexture9* m_D3Dtex;
uMod_IDirect3DVolumeTexture9* CrossRef_D3Dtex;
IDirect3DDevice9* m_D3Ddev;
int Reference;
MyTypeHash Hash;
bool FAKE;
IDirect3DVolumeTexture9* m_D3Dtex = nullptr;
uMod_IDirect3DVolumeTexture9* CrossRef_D3Dtex = nullptr;
IDirect3DDevice9* m_D3Ddev = nullptr;
TextureFileStruct* Reference = nullptr;
HashType Hash = 0u;
bool FAKE = false;
// original interface
STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj) override;
@@ -49,39 +46,5 @@ interface uMod_IDirect3DVolumeTexture9 : IDirect3DVolumeTexture9 {
STDMETHOD(UnlockBox)(UINT Level) override;
int GetHash(MyTypeHash& hash);
[[nodiscard]] HashType GetHash() const;
};
inline void UnswitchTextures(uMod_IDirect3DVolumeTexture9* pTexture)
{
uMod_IDirect3DVolumeTexture9* CrossRef = pTexture->CrossRef_D3Dtex;
if (CrossRef != nullptr) {
// switch textures back
IDirect3DVolumeTexture9* cpy = pTexture->m_D3Dtex;
pTexture->m_D3Dtex = CrossRef->m_D3Dtex;
CrossRef->m_D3Dtex = cpy;
// cancel the link
CrossRef->CrossRef_D3Dtex = nullptr;
pTexture->CrossRef_D3Dtex = nullptr;
}
}
inline int SwitchTextures(uMod_IDirect3DVolumeTexture9* pTexture1, uMod_IDirect3DVolumeTexture9* 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
IDirect3DVolumeTexture9* cpy = pTexture2->m_D3Dtex;
pTexture2->m_D3Dtex = pTexture1->m_D3Dtex;
pTexture1->m_D3Dtex = cpy;
return RETURN_OK;
}
return RETURN_TEXTURE_NOT_SWITCHED;
}
-10
View File
@@ -1,10 +0,0 @@
#pragma once
#include <string>
#include <vector>
#include <Windows.h>
struct UModTexture {
std::vector<char> data;
std::string name;
DWORD64 hash;
};
-69
View File
@@ -1,69 +0,0 @@
#pragma once
#include "uMod_IDirect3DTexture9.h"
#include "uMod_IDirect3DDevice9.h"
#include "uMod_Error.h"
#include "uMod_ArrayHandler.h"
class uMod_TextureServer;
/*
* An object of this class is owned by each d3d9 device.
* functions called by the Server are called from the server thread instance.
* All other functions are called from the render thread instance of the game itself.
*/
class uMod_TextureClient {
public:
uMod_TextureClient(uMod_TextureServer* server, IDirect3DDevice9* device);
~uMod_TextureClient();
int AddTexture(uMod_IDirect3DTexture9* tex); //called from uMod_IDirect3DDevice9::CreateTexture(...) or uMod_IDirect3DDevice9::BeginScene()
int AddTexture(uMod_IDirect3DVolumeTexture9* tex); //called from uMod_IDirect3DVolumeTexture9::CreateTexture(...) or uMod_IDirect3DDevice9::BeginScene()
int AddTexture(uMod_IDirect3DCubeTexture9* tex); //called from uMod_IDirect3DCubeTexture9::CreateTexture(...) or uMod_IDirect3DDevice9::BeginScene()
int RemoveTexture(uMod_IDirect3DTexture9* tex); //called from uMod_IDirect3DTexture9::Release()
int RemoveTexture(uMod_IDirect3DVolumeTexture9* tex); //called from uMod_IDirect3DVolumeTexture9::Release()
int RemoveTexture(uMod_IDirect3DCubeTexture9* tex); //called from uMod_IDirect3DCubeTexture9::Release()
int AddUpdate(TextureFileStruct* update, int number); //called from the Server, client object must delete update array
int MergeUpdate(); //called from uMod_IDirect3DDevice9::BeginScene()
int LookUpToMod(uMod_IDirect3DTexture9* pTexture, int num_index_list = 0, int* index_list = nullptr); // called at the end AddTexture(...) and from Device->UpdateTexture(...)
int LookUpToMod(uMod_IDirect3DVolumeTexture9* pTexture, int num_index_list = 0, int* index_list = nullptr); // called at the end AddTexture(...) and from Device->UpdateTexture(...)
int LookUpToMod(uMod_IDirect3DCubeTexture9* pTexture, int num_index_list = 0, int* index_list = nullptr); // called at the end AddTexture(...) and from Device->UpdateTexture(...)
uMod_TextureHandler<uMod_IDirect3DTexture9> OriginalTextures; // stores the pointer to the uMod_IDirect3DTexture9 objects created by the game
uMod_TextureHandler<uMod_IDirect3DVolumeTexture9> OriginalVolumeTextures; // stores the pointer to the uMod_IDirect3DVolumeTexture9 objects created by the game
uMod_TextureHandler<uMod_IDirect3DCubeTexture9> OriginalCubeTextures; // stores the pointer to the uMod_IDirect3DCubeTexture9 objects created by the game
D3DCOLOR FontColour;
D3DCOLOR TextureColour;
private:
uMod_TextureServer* Server;
IDirect3DDevice9* D3D9Device;
TextureFileStruct* Update;
int NumberOfUpdate;
int LockMutex();
int UnlockMutex();
HANDLE Mutex;
int NumberToMod; // number of texture to be modded
TextureFileStruct* FileToMod; // array which stores the file in memory and the hash of each texture to be modded
int LookUpToMod(MyTypeHash hash, int num_index_list, int* index_list); // called from LookUpToMod(...);
int LoadTexture(TextureFileStruct* file_in_memory, uMod_IDirect3DTexture9** ppTexture); // called if a target texture is found
int LoadTexture(TextureFileStruct* file_in_memory, uMod_IDirect3DVolumeTexture9** ppTexture); // called if a target texture is found
int LoadTexture(TextureFileStruct* file_in_memory, uMod_IDirect3DCubeTexture9** ppTexture); // called if a target texture is found
// and the corresponding fake texture should be loaded
//MyTypeHash GetHash(unsigned char *str, int len);
//unsigned int GetCRC32(char *pcDatabuf, unsigned int ulDatalen);
};
-48
View File
@@ -1,48 +0,0 @@
#pragma once
#include "uMod_GlobalDefines.h"
#include "uMod_ArrayHandler.h"
/*
* An object of this class is created only once.
* The Mainloop functions is executed by a server thread,
* which listen on a pipe.
*
* Functions called by the Client are called from the a thread instance of the game itself.
* Nearly all other functions are called from the server thread instance.
*/
class uMod_TextureClient;
class uMod_TextureServer {
public:
uMod_TextureServer(char* name, char* uModName);
~uMod_TextureServer();
int AddClient(uMod_TextureClient* client, TextureFileStruct** update, int* number); // called from a Client
int Initialize(); // is executed in a server thread
// following functions are only public for testing purpose !!
// they should be private and only be called from the Mainloop
int AddFile(char* buffer, unsigned int size, MyTypeHash hash, bool force); // called from Mainloop(), if the content of the texture is sent
private:
wchar_t GameName[MAX_PATH];
char UModName[MAX_PATH];
void LoadModsFromFile(const char* source);
int PropagateUpdate(uMod_TextureClient* client = nullptr); // called from Mainloop() if texture are loaded or removed
int PrepareUpdate(TextureFileStruct** update, int* number); // called from PropagateUpdate() and AddClient()
// generate a copy of the current texture to be modded
// the file content of the textures are not copied, the clients get the pointer to the file content
// but the arrays allocate by this function, must be deleted by the client
uMod_TextureClient* Client;
uMod_FileHandler CurrentMod; // hold the file content of texture
uMod_FileHandler OldMod; // hold the file content of texture which were added previously but are not needed any more
// this is needed, because a texture clients might not have merged the last update and thus hold pointers to the file content of old textures
};
-157
View File
@@ -1,157 +0,0 @@
#pragma once
#include <string>
#include <Windows.h>
void ReplaceAll(std::wstring& str, const std::wstring& from, const std::wstring& to)
{
if (from.empty()) {
return;
}
size_t startPos = 0;
while ((startPos = str.find(from, startPos)) != std::wstring::npos) {
str.replace(startPos, from.length(), to);
startPos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
}
void ReplaceAll(std::string& str, const std::string& from, const std::string& to)
{
if (from.empty()) {
return;
}
size_t startPos = 0;
while ((startPos = str.find(from, startPos)) != std::string::npos) {
str.replace(startPos, from.length(), to);
startPos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
}
std::wstring AfterFirst(const std::wstring& str, wchar_t delimiter)
{
const size_t pos = str.find(delimiter);
if (pos != std::wstring::npos) {
// Return the substring after the delimiter
return str.substr(pos + 1);
}
// If the delimiter is not found, return an empty string
return L"";
}
std::string AfterFirst(const std::string& str, char delimiter)
{
const size_t pos = str.find(delimiter);
if (pos != std::string::npos) {
// Return the substring after the delimiter
return str.substr(pos + 1);
}
// If the delimiter is not found, return an empty string
return "";
}
std::wstring BeforeFirst(const std::wstring& str, wchar_t delimiter)
{
const size_t pos = str.find(delimiter);
return pos != std::wstring::npos ? str.substr(0, pos) : str;
}
std::string BeforeFirst(const std::string& str, char delimiter)
{
const size_t pos = str.find(delimiter);
return pos != std::string::npos ? str.substr(0, pos) : str;
}
std::string BeforeLast(const std::string& file_path, char separator)
{
// Find the last occurrence of '.'
const std::size_t last_dot_pos = file_path.find_last_of(separator);
// If there is a dot, and it is not at the beginning of the filename
if (last_dot_pos != std::string::npos && last_dot_pos != 0) {
// Extract the substring from the dot to the end of the string
return file_path.substr(0, last_dot_pos);
}
// If the dot is not found, or is the first character, return an empty string
return "";
}
std::wstring BeforeLast(const std::wstring& file_path, wchar_t separator)
{
// Find the last occurrence of '.'
const std::size_t last_dot_pos = file_path.find_last_of(separator);
// If there is a dot, and it is not at the beginning of the filename
if (last_dot_pos != std::wstring::npos && last_dot_pos != 0) {
// Extract the substring from the dot to the end of the string
return file_path.substr(0, last_dot_pos);
}
// If the dot is not found, or is the first character, return an empty string
return L"";
}
std::string AfterLast(const std::string& file_path, char separator)
{
// Find the last occurrence of '.'
const std::size_t last_dot_pos = file_path.find_last_of(separator);
// If there is a dot, and it is not at the beginning of the filename
if (last_dot_pos != std::string::npos && last_dot_pos != 0) {
// Extract the substring from the dot to the end of the string
return file_path.substr(last_dot_pos + 1);
}
// If the dot is not found, or is the first character, return an empty string
return "";
}
std::wstring AfterLast(const std::wstring& file_path, wchar_t separator)
{
// Find the last occurrence of '.'
const std::size_t last_dot_pos = file_path.find_last_of(separator);
// If there is a dot, and it is not at the beginning of the filename
if (last_dot_pos != std::wstring::npos && last_dot_pos != 0) {
// Extract the substring from the dot to the end of the string
return file_path.substr(last_dot_pos + 1);
}
// If the dot is not found, or is the first character, return an empty string
return L"";
}
std::string GetFileExtension(const std::string& file_path)
{
// Find the last occurrence of '.'
const std::size_t last_dot_pos = file_path.find_last_of(".");
// If there is a dot, and it is not at the beginning of the filename
if (last_dot_pos != std::string::npos && last_dot_pos != 0) {
// Extract the substring from the dot to the end of the string
return file_path.substr(last_dot_pos + 1);
}
// If the dot is not found, or is the first character, return an empty string
return "";
}
std::string WideStringToString(const std::wstring& wstr)
{
if (wstr.empty()) {
return std::string();
}
const int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast<int>(wstr.size()), nullptr, 0, nullptr, nullptr);
std::string strTo(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, &wstr[0], static_cast<int>(wstr.size()), &strTo[0], size_needed, nullptr, nullptr);
return strTo;
}
std::wstring StringToWString(const std::string& str)
{
if (str.empty()) {
return std::wstring();
}
const int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast<int>(str.size()), nullptr, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], static_cast<int>(str.size()), &wstrTo[0], size_needed);
return wstrTo;
}