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
+14
View File
@@ -5,6 +5,15 @@
*.vscode
*.project
*.cproject
*.vcproj
*.vcxproj
*.vcxproj.filters
**/CMakeFiles/**
cmake_install.cmake
CMakeCache.txt
*.sln
*.rc
/*.dir
# Build directories
Release
@@ -46,7 +55,12 @@ bin/
*.opendb
*.wixpdb
**/RelWithDebInfo/
**/Debug/
/bin
/win32
/out
/build
/_deps
.idea
+3 -1
View File
@@ -17,7 +17,7 @@ endif()
set(VERSION_MAJOR 1)
set(VERSION_MINOR 5)
set(VERSION_PATCH 5)
set(VERSION_PATCH 6)
set(VERSION_TWEAK 0)
set(VERSION_RC "${CMAKE_CURRENT_BINARY_DIR}/version.rc")
@@ -49,6 +49,7 @@ endif()
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
include(libzippp)
include(minhook)
add_library(gMod SHARED)
@@ -72,6 +73,7 @@ target_link_libraries(gMod PRIVATE
${DXGUID_LIB}
libzippp
psapi
minhook
)
target_link_options(gMod PRIVATE
"$<$<CONFIG:DEBUG>:/NODEFAULTLIB:LIBCMT>"
+1 -1
View File
@@ -21,7 +21,7 @@ if (NOT libzippp_POPULATED)
FetchContent_Populate(libzippp)
endif()
add_library(libzippp)
add_library(libzippp STATIC)
set(SOURCES
"${libzippp_SOURCE_DIR}/src/libzippp.h"
+16
View File
@@ -0,0 +1,16 @@
include_guard()
include(FetchContent)
FetchContent_Declare(
minhook
GIT_REPOSITORY https://github.com/TsudaKageyu/minhook
GIT_TAG master)
FetchContent_GetProperties(minhook)
if (NOT minhook_POPULATED)
FetchContent_Populate(minhook)
endif()
add_subdirectory(${minhook_SOURCE_DIR} EXCLUDE_FROM_ALL)
set_target_properties(minhook PROPERTIES FOLDER "Dependencies/")
+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;
}
+23
View File
@@ -0,0 +1,23 @@
#include "Error.h"
#include <Windows.h>
#include <stdio.h>
#include <process.h>
__declspec(noreturn) void FatalAssert(
const char *expr,
const char *file,
unsigned int line,
const char *function)
{
const char* fmt = "%s\n%s\n%s line %d";
int len = snprintf(NULL, 0, fmt, expr, file, function, line);
char* buf = new char[len + 1];
snprintf(buf,len + 1, fmt, expr, file, function, line);
MessageBox(0, "uMod Assertion", buf, MB_OK | MB_ICONERROR);
delete[] buf;
abort();
}
@@ -1,14 +1,14 @@
#include <uMod_Main.h>
#include <..\header\Main.h>
#include <filesystem>
#include "gMod_FileLoader.h"
#include "XorStreamReader.h"
#include "FileLoader.h"
#include "TpfReader.h"
gMod_FileLoader::gMod_FileLoader(const std::string& fileName)
FileLoader::FileLoader(const std::string& fileName)
{
file_name = std::filesystem::absolute(fileName).string();
}
std::vector<TpfEntry> gMod_FileLoader::GetContents()
std::vector<TpfEntry> FileLoader::GetContents()
{
try {
return file_name.ends_with(".tpf") ? GetTpfContents() : GetFileContents();
@@ -19,11 +19,11 @@ std::vector<TpfEntry> gMod_FileLoader::GetContents()
return {};
}
std::vector<TpfEntry> gMod_FileLoader::GetTpfContents()
std::vector<TpfEntry> FileLoader::GetTpfContents()
{
std::vector<TpfEntry> entries;
auto xorreader = XorStreamReader(file_name);
const auto buffer = xorreader.ReadToEnd();
auto tpf_reader = TpfReader(file_name);
const auto buffer = tpf_reader.ReadToEnd();
const auto zip_archive = libzippp::ZipArchive::fromBuffer(buffer.data(), buffer.size(), false, TPF_PASSWORD);
if (!zip_archive) {
Message("Failed to open tpf file: %s - %u bytes!", file_name.c_str(), buffer.size());
@@ -41,7 +41,7 @@ std::vector<TpfEntry> gMod_FileLoader::GetTpfContents()
return entries;
}
std::vector<TpfEntry> gMod_FileLoader::GetFileContents()
std::vector<TpfEntry> FileLoader::GetFileContents()
{
std::vector<TpfEntry> entries;
@@ -58,8 +58,6 @@ void ParseSimpleArchive(const libzippp::ZipArchive& archive, std::vector<TpfEntr
for (const auto& entry : archive.getEntries()) {
if (entry.isFile()) {
//TODO: #6 - Implement regex search
const auto dataPtr = entry.readAsBinary();
const auto size = entry.getSize();
auto name = entry.getName();
// Remove the part before the last underscore (if any)
@@ -81,9 +79,9 @@ void ParseSimpleArchive(const libzippp::ZipArchive& archive, std::vector<TpfEntr
name = name.substr(0, lastIndex);
}
uint32_t crcHash;
uint32_t crc_hash;
try {
crcHash = std::stoul(name, nullptr, 16);
crc_hash = std::stoul(name, nullptr, 16);
}
catch (const std::invalid_argument& e) {
Message("Failed to parse %s as a hash", name.c_str());
@@ -94,7 +92,11 @@ void ParseSimpleArchive(const libzippp::ZipArchive& archive, std::vector<TpfEntr
continue;
}
entries.push_back({name, entry.getName(), crcHash, dataPtr, size});
const auto data_ptr = static_cast<char*>(entry.readAsBinary());
const auto size = entry.getSize();
std::vector<char> vec;
vec.assign(data_ptr, data_ptr + size);
entries.emplace_back(name, entry.getName(), crc_hash, std::move(vec));
}
}
}
@@ -124,9 +126,8 @@ void ParseTexmodArchive(std::vector<std::string>& lines, libzippp::ZipArchive& a
}
// Remove trailing newline and carriage return characters
const size_t endpos = path.find_last_not_of("\r\n");
if (endpos != std::string::npos) {
path.erase(endpos + 1);
if (const auto end_pos = path.find_last_not_of("\r\n"); end_pos != std::string::npos) {
path.erase(end_pos + 1);
}
else if (!path.empty()) {
path.clear();
@@ -141,11 +142,9 @@ void ParseTexmodArchive(std::vector<std::string>& lines, libzippp::ZipArchive& a
continue;
}
const auto data_ptr = entry.readAsBinary();
const auto size = entry.getSize();
uint32_t crcHash;
uint32_t crc_hash{};
try {
crcHash = std::stoul(addrstr, nullptr, 16);
crc_hash = std::stoul(addrstr, nullptr, 16);
}
catch (const std::invalid_argument& e) {
Message("Failed to parse %s as a hash", addrstr.c_str());
@@ -156,11 +155,15 @@ void ParseTexmodArchive(std::vector<std::string>& lines, libzippp::ZipArchive& a
continue;
}
entries.push_back({addrstr, entry.getName(), crcHash, data_ptr, size});
const auto data_ptr = static_cast<char*>(entry.readAsBinary());
const auto size = static_cast<size_t>(entry.getSize());
std::vector vec(data_ptr, data_ptr + size);
entries.emplace_back(addrstr, entry.getName(), crc_hash, std::move(vec));
delete[] data_ptr;
}
}
void gMod_FileLoader::LoadEntries(libzippp::ZipArchive& archive, std::vector<TpfEntry>& entries)
void FileLoader::LoadEntries(libzippp::ZipArchive& archive, std::vector<TpfEntry>& entries)
{
// Iterate over the files in the zip archive
const auto def_file = archive.getEntry("texmod.def");
+208
View File
@@ -0,0 +1,208 @@
#include <filesystem>
#include <fstream>
#include "Main.h"
TextureClient::TextureClient(IDirect3DDevice9* device)
{
Message("TextureClient::TextureClient(): %p\n", this);
D3D9Device = device;
void* cpy;
isDirectXExDevice = D3D9Device->QueryInterface(IID_IDirect3DTexture9, &cpy) == 0x01000001L;
Mutex = CreateMutex(nullptr, false, nullptr);
FontColour = D3DCOLOR_ARGB(255, 255, 0, 0);
TextureColour = D3DCOLOR_ARGB(255, 0, 255, 0);
}
TextureClient::~TextureClient()
{
Message("TextureClient::~TextureClient(): %p\n", this);
if (Mutex != nullptr) {
CloseHandle(Mutex);
}
for (const auto& it : modded_textures) {
delete it.second;
}
modded_textures.clear();
}
int TextureClient::MergeUpdate()
{
if (!should_update) return RETURN_OK;
should_update = false;
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_TEXTURE;
return ret;
}
Message("MergeUpdate(): %p\n", this);
const auto single_texture = GetSingleTexture();
for (const auto pTexture : OriginalTextures) {
if (pTexture->CrossRef_D3Dtex == nullptr || pTexture->CrossRef_D3Dtex == single_texture) {
UnswitchTextures(pTexture); //this we can do always, so we unswitch the single texture
LookUpToMod(pTexture);
}
}
const auto single_volume_texture = GetSingleVolumeTexture();
for (const auto pTexture : OriginalVolumeTextures) {
if (pTexture->CrossRef_D3Dtex == nullptr || pTexture->CrossRef_D3Dtex == single_volume_texture) {
UnswitchTextures(pTexture); //this we can do always, so we unswitch the single texture
LookUpToMod(pTexture);
}
}
const auto single_cube_texture = GetSingleCubeTexture();
for (const auto pTexture : OriginalCubeTextures) {
if (pTexture->CrossRef_D3Dtex == nullptr || pTexture->CrossRef_D3Dtex == single_cube_texture) {
UnswitchTextures(pTexture); //this we can do always, so we unswitch the single texture
LookUpToMod(pTexture);
}
}
return UnlockMutex();
}
uMod_IDirect3DTexture9* TextureClient::GetSingleTexture()
{
if (isDirectXExDevice)
return static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->GetSingleTexture();
//this texture must no be added twice
return static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->GetSingleTexture();
}
uMod_IDirect3DVolumeTexture9* TextureClient::GetSingleVolumeTexture()
{
if (isDirectXExDevice)
return static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->GetSingleVolumeTexture();
//this texture must no be added twice
return static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->GetSingleVolumeTexture();
}
uMod_IDirect3DCubeTexture9* TextureClient::GetSingleCubeTexture()
{
if (isDirectXExDevice)
return static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->GetSingleCubeTexture();
//this texture must no be added twice
return static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->GetSingleCubeTexture();
}
int TextureClient::SetLastCreatedTexture(uMod_IDirect3DTexture9* texture)
{
if (isDirectXExDevice)
return static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->SetLastCreatedTexture(texture);
//this texture must no be added twice
return static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->SetLastCreatedTexture(texture);
}
int TextureClient::SetLastCreatedVolumeTexture(uMod_IDirect3DVolumeTexture9* texture)
{
if (isDirectXExDevice)
return static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->SetLastCreatedVolumeTexture(texture);
//this texture must no be added twice
return static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->SetLastCreatedVolumeTexture(texture);
}
int TextureClient::SetLastCreatedCubeTexture(uMod_IDirect3DCubeTexture9* texture)
{
if (isDirectXExDevice)
return static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->SetLastCreatedCubeTexture(texture);
//this texture must no be added twice
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(Mutex, 100)) {
return RETURN_MUTEX_LOCK; //waiting 100ms, to wait infinite pass INFINITE
}
return RETURN_OK;
}
int TextureClient::UnlockMutex()
{
if (ReleaseMutex(Mutex) == 0) {
return RETURN_MUTEX_UNLOCK;
}
return RETURN_OK;
}
unsigned long TextureClient::AddFile(TpfEntry& entry)
{
if (modded_textures.contains(entry.crc_hash)) {
return 0;
}
TextureFileStruct* texture_file_struct = new TextureFileStruct();
texture_file_struct->data = std::move(entry.data);
texture_file_struct->crc_hash = entry.crc_hash;
modded_textures.emplace(entry.crc_hash, texture_file_struct);
should_update = true;
return texture_file_struct->data.size();
}
void TextureClient::LoadModsFromFile(const char* source)
{
static unsigned long loaded_size = 0;
Message("Initialize: searching in %s\n", source);
std::ifstream file(source);
if (!file.is_open()) {
Message("LoadModsFromFile: failed to open modlist.txt for reading; aborting!!!");
return;
}
Message("Initialize: found modlist.txt. Reading\n");
std::string line;
while (std::getline(file, line)) {
Message("Initialize: loading file %s... ", line.c_str());
// Remove newline character
line.erase(std::ranges::remove(line, '\n').begin(), line.end());
auto file_loader = FileLoader(line);
auto entries = file_loader.GetContents();
if (loaded_size > 1'500'000'000) {
Message("LoadModsFromFile: Loaded %d bytes, aborting!!!\n", loaded_size);
return;
}
if (entries.empty()) {
Message("No entries found.\n");
continue;
}
Message("%zu textures... ", entries.size());
unsigned long file_bytes_loaded = 0;
for (auto& tpf_entry : entries) {
file_bytes_loaded += AddFile(tpf_entry);
}
entries.clear();
Message("%d bytes loaded.\n", file_bytes_loaded);
loaded_size += file_bytes_loaded;
}
Message("Finished loading mods from %s: Loaded %u bytes (%u mb)", source, loaded_size, loaded_size / 1024 / 1024);
}
void TextureClient::Initialize()
{
Message("Initialize: begin\n");
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
char dllpath[MAX_PATH]{};
GetModuleFileName(gl_hThisInstance, dllpath, MAX_PATH); //ask for name and path of this dll
const auto exe = std::filesystem::path(gwpath).parent_path();
const auto dll = std::filesystem::path(dllpath).parent_path();
for (const auto& path : {exe, dll}) {
const auto modlist = path / "modlist.txt";
if (std::filesystem::exists(modlist)) {
Message("Initialize: found %s\n", modlist.string().c_str());
LoadModsFromFile(modlist.string().c_str());
}
}
Message("Initialize: end\n");
}
+203
View File
@@ -0,0 +1,203 @@
#include "dll_main.h"
#include <array>
#include <Windows.h>
#include "Main.h"
#include <Psapi.h>
#include "MinHook.h"
namespace {
using Direct3DCreate9_type = IDirect3D9* (APIENTRY*)(UINT);
using Direct3DCreate9Ex_type = HRESULT(APIENTRY*)(UINT SDKVersion, IDirect3D9Ex** ppD3D);
// Pointer to original address of Direct3DCreate9
Direct3DCreate9_type Direct3DCreate9_fn = nullptr;
Direct3DCreate9_type Direct3DCreate9_ret = nullptr;
// Pointer to original address of Direct3DCreate9
Direct3DCreate9Ex_type Direct3DCreate9Ex_fn = nullptr;
Direct3DCreate9Ex_type Direct3DCreate9Ex_ret = nullptr;
static FILE* stdout_proxy;
static FILE* stderr_proxy;
/*
* global variable which are linked external
*/
unsigned int gl_ErrorState = 0u;
// If not nullptr, we're responsible for freeing this library on termination
HMODULE gl_hOriginalDll = nullptr;
// If this hModule called d3d9.dll?
bool IsD3d9Module(HMODULE hModule, HANDLE hProcess)
{
TCHAR szModuleName[MAX_PATH];
GetModuleBaseName(hProcess, hModule, szModuleName, sizeof(szModuleName) / sizeof(TCHAR));
return strcmp(szModuleName, TEXT("d3d9.dll")) == 0;
}
// Does this module contain exported function calls for creating a d3d9 device?
bool HasD3d9Methods(HMODULE hModule, HANDLE hProcess)
{
return GetProcAddress(hModule, "Direct3DCreate9")
&& GetProcAddress(hModule, "Direct3DCreate9Ex");
}
HMODULE FindLoadedDll()
{
HMODULE hModules[1024];
HANDLE hProcess;
DWORD cbNeeded;
unsigned int i;
// Get a handle to the current process.
hProcess = GetCurrentProcess();
if (!EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded))
return nullptr;
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
if (IsD3d9Module(hModules[i], hProcess)
|| HasD3d9Methods(hModules[i], hProcess)) {
return hModules[i];
}
}
return nullptr;
}
}
unsigned int gl_ErrorState = 0;
HINSTANCE gl_hThisInstance = nullptr;
/*
* dll entry routine, here we initialize or clean up
*/
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(lpReserved);
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH: {
#ifdef _DEBUG
AllocConsole();
SetConsoleTitleA("gMod Console");
freopen_s(&stdout_proxy, "CONOUT$", "w", stdout);
freopen_s(&stderr_proxy, "CONOUT$", "w", stderr);
#endif
InitInstance(hModule);
break;
}
case DLL_PROCESS_DETACH: {
ExitInstance();
break;
}
default: break;
}
return true;
}
void InitInstance(HINSTANCE hModule)
{
DisableThreadLibraryCalls(hModule); //reduce overhead
gl_hThisInstance = hModule;
Message("InitInstance: %p\n", hModule);
const auto d3d9_dll = LoadOriginalDll();
ASSERT(d3d9_dll);
Direct3DCreate9_fn = reinterpret_cast<Direct3DCreate9_type>(GetProcAddress(d3d9_dll, "Direct3DCreate9"));
ASSERT(Direct3DCreate9_fn);
Direct3DCreate9Ex_fn = reinterpret_cast<Direct3DCreate9Ex_type>(GetProcAddress(d3d9_dll, "Direct3DCreate9Ex"));
ASSERT(Direct3DCreate9Ex_fn);
MH_Initialize();
if (Direct3DCreate9_fn) {
MH_CreateHook(Direct3DCreate9_fn, uMod_Direct3DCreate9, (void**)&Direct3DCreate9_ret);
MH_EnableHook(Direct3DCreate9_fn);
}
if (Direct3DCreate9Ex_fn) {
MH_CreateHook(Direct3DCreate9Ex_fn, uMod_Direct3DCreate9Ex, (void**)&Direct3DCreate9Ex_ret);
MH_EnableHook(Direct3DCreate9Ex_fn);
}
}
void ExitInstance()
{
if(Direct3DCreate9_fn)
MH_DisableHook(Direct3DCreate9_fn);
if(Direct3DCreate9Ex_fn)
MH_DisableHook(Direct3DCreate9Ex_fn);
MH_Uninitialize();
// Release the system's d3d9.dll
if (gl_hOriginalDll != nullptr) {
FreeLibrary(gl_hOriginalDll);
gl_hOriginalDll = nullptr;
}
#ifdef _DEBUG
if (stdout_proxy)
fclose(stdout_proxy);
if (stderr_proxy)
fclose(stderr_proxy);
FreeConsole();
#endif
}
HMODULE LoadOriginalDll()
{
HMODULE found = FindLoadedDll();
if (found)
return found;
char buffer[MAX_PATH];
GetSystemDirectory(buffer, MAX_PATH); //get the system directory, we need to open the original d3d9.dll
// Append dll name
strcat_s(buffer, MAX_PATH, "\\d3d9.dll");
gl_hOriginalDll = LoadLibrary(buffer);
found = FindLoadedDll();
ASSERT(found && found == gl_hOriginalDll);
return found;
}
/*
* We inject the dll into the game, thus we retour the original Direct3DCreate9 function to our MyDirect3DCreate9 function
*/
IDirect3D9* APIENTRY uMod_Direct3DCreate9(UINT SDKVersion)
{
Message("uMod_Direct3DCreate9: original %p, uMod %p\n", Direct3DCreate9_fn, uMod_Direct3DCreate9);
ASSERT(Direct3DCreate9_ret);
IDirect3D9* pIDirect3D9_orig = Direct3DCreate9_ret(SDKVersion); //creating the original IDirect3D9 object
ASSERT(pIDirect3D9_orig);
return new uMod_IDirect3D9(pIDirect3D9_orig); //return our object instead of the "real one"
}
HRESULT APIENTRY uMod_Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex** ppD3D)
{
Message("uMod_Direct3DCreate9Ex: original %p, uMod %p\n", Direct3DCreate9Ex_fn, uMod_Direct3DCreate9Ex);
ASSERT(Direct3DCreate9Ex_ret);
IDirect3D9Ex* pIDirect3D9Ex_orig = nullptr;
HRESULT ret = Direct3DCreate9Ex_ret(SDKVersion, &pIDirect3D9Ex_orig); //creating the original IDirect3D9 object
if (ret != S_OK)
return ret;
// @Cleanup: should be we freeing pIDirect3D9Ex at the end of our own lifecycle?
uMod_IDirect3D9Ex* pIDirect3D9Ex = new uMod_IDirect3D9Ex(pIDirect3D9Ex_orig);
ppD3D = (IDirect3D9Ex**)&pIDirect3D9Ex;
return ret;
}
-92
View File
@@ -1,92 +0,0 @@
#include "uMod_Main.h"
uMod_FileHandler::uMod_FileHandler()
{
Message("uMod_FileHandler(): %p\n", this);
}
uMod_FileHandler::~uMod_FileHandler()
{
Message("~uMod_FileHandler(): %p\n", this);
if (Files != nullptr) {
for (int i = 0; i < FieldCounter; i++) {
delete [] Files[i];
}
delete [] Files;
}
}
int uMod_FileHandler::Add(TextureFileStruct* file)
{
Message("uMod_FileHandler::Add(%p): %p\n", file, this);
if (gl_ErrorState & uMod_ERROR_FATAL) {
return RETURN_FATAL_ERROR;
}
if (file->Reference >= 0) {
return RETURN_UPDATE_ALLREADY_ADDED;
}
if (Number / FieldLength == FieldCounter) // get more memory
{
TextureFileStruct*** temp = nullptr;
try { temp = new TextureFileStruct**[FieldCounter + 10]; }
catch (...) {
gl_ErrorState |= uMod_ERROR_MEMORY | uMod_ERROR_TEXTURE;
return RETURN_NO_MEMORY;
}
for (int i = 0; i < FieldCounter; i++) {
temp[i] = Files[i]; //copy to new allocated memory
}
for (int i = FieldCounter; i < FieldCounter + 10; i++) {
temp[i] = nullptr; // initialize unused parts to zero
}
FieldCounter += 10;
delete [] Files;
Files = temp;
}
if (Number % FieldLength == 0) // maybe we need to get more memory
{
try {
if (Files[Number / FieldLength] == nullptr) {
Files[Number / FieldLength] = new TextureFileStruct*[FieldLength];
}
}
catch (...) {
Files[Number / FieldLength] = nullptr;
gl_ErrorState |= uMod_ERROR_MEMORY | uMod_ERROR_TEXTURE;
return RETURN_NO_MEMORY;
}
}
Files[Number / FieldLength][Number % FieldLength] = file;
file->Reference = Number++; //set the reference for a fast deleting
return RETURN_OK;
}
int uMod_FileHandler::Remove(TextureFileStruct* file)
{
Message("uMod_FileHandler::Remove(%p): %p\n", file, this);
if (gl_ErrorState & uMod_ERROR_FATAL) {
return RETURN_FATAL_ERROR;
}
const int ref = file->Reference;
if (ref < 0) {
return RETURN_OK; // returning if no Reference is set
}
file->Reference = -1; //set reference outside of bound
if (ref < (--Number)) //if reference is unequal to Number-1 we copy the last entry to the index "ref"
{
Files[ref / FieldLength][ref % FieldLength] = Files[Number / FieldLength][Number % FieldLength];
Files[ref / FieldLength][ref % FieldLength]->Reference = ref; //set the new reference entry
}
return RETURN_OK;
}
-326
View File
@@ -1,326 +0,0 @@
#include "uMod_DX9_dll.h"
#include <array>
#include <Windows.h>
#include "uMod_Main.h"
#include <Psapi.h>
HINSTANCE gl_hOriginalDll = nullptr;
HINSTANCE gl_hThisInstance = nullptr;
std::unique_ptr<uMod_TextureServer> gl_TextureServer = nullptr;
using Direct3DCreate9_type = IDirect3D9* (APIENTRY*)(UINT);
using Direct3DCreate9Ex_type = HRESULT(APIENTRY*)(UINT SDKVersion, IDirect3D9Ex** ppD3D);
Direct3DCreate9_type Direct3DCreate9_fn; // we need to store the pointer to the original Direct3DCreate9 function after we have done a detour
Direct3DCreate9Ex_type Direct3DCreate9Ex_fn; // we need to store the pointer to the original Direct3DCreate9 function after we have done a detour
HHOOK gl_hHook = nullptr;
static FILE* stdout_proxy;
static FILE* stderr_proxy;
/*
* global variable which are linked external
*/
unsigned int gl_ErrorState = 0u;
#ifdef LOG_MESSAGE
FILE* gl_File = nullptr;
#endif
#ifdef DIRECT_INJECTION
void Nothing() { (void)NULL; }
#endif
/*
* dll entry routine, here we initialize or clean up
*/
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(lpReserved);
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH: {
#ifdef _DEBUG
AllocConsole();
SetConsoleTitleA("gMod Console");
freopen_s(&stdout_proxy, "CONOUT$", "w", stdout);
freopen_s(&stderr_proxy, "CONOUT$", "w", stderr);
#endif
InitInstance(hModule);
break;
}
case DLL_PROCESS_DETACH: {
ExitInstance();
break;
}
default: break;
}
return true;
}
void InitInstance(HINSTANCE hModule)
{
DisableThreadLibraryCalls(hModule); //reduce overhead
gl_hThisInstance = hModule;
char game[MAX_PATH];
if (HookThisProgram(game)) //ask if we need to hook this program
{
OpenMessage();
Message("InitInstance: %p\n", hModule);
std::array<char, MAX_PATH> uMod{};
GetModuleFileNameA(hModule, uMod.data(), MAX_PATH);
Message("InitInstance: %s\n", uMod.data());
gl_TextureServer = std::make_unique<uMod_TextureServer>(game, uMod.data()); //create the server which listen on the pipe and prepare the update for the texture clients
LoadOriginalDll();
if (gl_hOriginalDll) {
Direct3DCreate9_fn = reinterpret_cast<Direct3DCreate9_type>(GetProcAddress(gl_hOriginalDll, "Direct3DCreate9"));
if (Direct3DCreate9_fn != nullptr) {
Message("Detour: Direct3DCreate9\n");
Direct3DCreate9_fn = static_cast<Direct3DCreate9_type>(DetourFunc((BYTE*)Direct3DCreate9_fn, (BYTE*)uMod_Direct3DCreate9, 5));
}
Direct3DCreate9Ex_fn = reinterpret_cast<Direct3DCreate9Ex_type>(GetProcAddress(gl_hOriginalDll, "Direct3DCreate9Ex"));
if (Direct3DCreate9Ex_fn != nullptr) {
Message("Detour: Direct3DCreate9Ex\n");
Direct3DCreate9Ex_fn = static_cast<Direct3DCreate9Ex_type>(DetourFunc((BYTE*)Direct3DCreate9Ex_fn, (BYTE*)uMod_Direct3DCreate9Ex, 7));
}
}
gl_TextureServer->Initialize();
}
}
bool HasDesiredMethods(HMODULE hModule, HANDLE hProcess)
{
const auto d3dcreate9Addr = GetProcAddress(hModule, "Direct3DCreate9");
if (!d3dcreate9Addr) {
return false;
}
const auto d3dcreate9ExAddr = GetProcAddress(hModule, "Direct3DCreate9Ex");
if (!d3dcreate9ExAddr) {
return false;
}
return true;
}
bool IsDesiredModule(HMODULE hModule, HANDLE hProcess)
{
TCHAR szModuleName[MAX_PATH];
GetModuleBaseName(hProcess, hModule, szModuleName, sizeof(szModuleName) / sizeof(TCHAR));
return strcmp(szModuleName, TEXT("d3d9.dll")) == 0;
}
bool FindLoadedDll()
{
HMODULE hModules[1024];
HANDLE hProcess;
DWORD cbNeeded;
unsigned int i;
// Get a handle to the current process.
hProcess = GetCurrentProcess();
if (EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded)) {
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
if (IsDesiredModule(hModules[i], hProcess)) {
// If the module is d3d9.dll, store the handle or do your hooking here.
gl_hOriginalDll = hModules[i];
break;
}
if (HasDesiredMethods(hModules[i], hProcess)) {
// If the module has the two specific methods, store the handle or do your hooking here.
gl_hOriginalDll = hModules[i];
break;
}
}
}
if (gl_hOriginalDll) {
return true;
}
return false;
}
void LoadOriginalDll()
{
if (FindLoadedDll()) {
return;
}
char buffer[MAX_PATH];
GetSystemDirectory(buffer, MAX_PATH); //get the system directory, we need to open the original d3d9.dll
// Append dll name
strcat_s(buffer, MAX_PATH, "\\d3d9.dll");
// try to load the system's d3d9.dll, if pointer empty
if (!gl_hOriginalDll) {
gl_hOriginalDll = LoadLibrary(buffer);
}
if (!gl_hOriginalDll) {
ExitProcess(0); // exit the hard way
}
}
void ExitInstance()
{
// Release the system's d3d9.dll
if (gl_hOriginalDll != nullptr) {
FreeLibrary(gl_hOriginalDll);
gl_hOriginalDll = nullptr;
}
#ifdef _DEBUG
if (stdout_proxy)
fclose(stdout_proxy);
if (stderr_proxy)
fclose(stderr_proxy);
FreeConsole();
#endif
CloseMessage();
}
/*
* We inject the dll into the game, thus we retour the original Direct3DCreate9 function to our MyDirect3DCreate9 function
*/
IDirect3D9* APIENTRY uMod_Direct3DCreate9(UINT SDKVersion)
{
Message("uMod_Direct3DCreate9: original %p, uMod %p\n", Direct3DCreate9_fn, uMod_Direct3DCreate9);
// in the Internet are many tutorials for detouring functions and all of them will work without the following 5 marked lines
// but somehow, for me it only works, if I retour the function and calling afterward the original function
// BEGIN
LoadOriginalDll();
RetourFunc((BYTE*)GetProcAddress(gl_hOriginalDll, "Direct3DCreate9"), (BYTE*)Direct3DCreate9_fn, 5);
Direct3DCreate9_fn = (Direct3DCreate9_type)GetProcAddress(gl_hOriginalDll, "Direct3DCreate9");
/*
if (Direct3DCreate9Ex_fn!=NULL)
{
RetourFunc((BYTE*) GetProcAddress( gl_hOriginalDll, "Direct3DCreate9Ex"), (BYTE*)Direct3DCreate9Ex_fn, 7);
Direct3DCreate9Ex_fn = (Direct3DCreate9Ex_type) GetProcAddress( gl_hOriginalDll, "Direct3DCreate9Ex");
}
*/
// END
IDirect3D9* pIDirect3D9_orig = nullptr;
if (Direct3DCreate9_fn) {
pIDirect3D9_orig = Direct3DCreate9_fn(SDKVersion); //creating the original IDirect3D9 object
}
else {
return nullptr;
}
uMod_IDirect3D9* pIDirect3D9;
if (pIDirect3D9_orig) {
pIDirect3D9 = new uMod_IDirect3D9(pIDirect3D9_orig, gl_TextureServer.get()); //creating our uMod_IDirect3D9 object
}
// we detour again
Direct3DCreate9_fn = static_cast<Direct3DCreate9_type>(DetourFunc((BYTE*)Direct3DCreate9_fn, (BYTE*)uMod_Direct3DCreate9, 5));
/*
if (Direct3DCreate9Ex_fn!=NULL)
{
Direct3DCreate9Ex_fn = (Direct3DCreate9Ex_type)DetourFunc( (BYTE*) Direct3DCreate9Ex_fn, (BYTE*)uMod_Direct3DCreate9Ex,7);
}
*/
return pIDirect3D9; //return our object instead of the "real one"
}
HRESULT APIENTRY uMod_Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex** ppD3D)
{
Message("uMod_Direct3DCreate9Ex: original %p, uMod %p\n", Direct3DCreate9Ex_fn, uMod_Direct3DCreate9Ex);
// in the Internet are many tutorials for detouring functions and all of them will work without the following 5 marked lines
// but somehow, for me it only works, if I retour the function and calling afterward the original function
// BEGIN
LoadOriginalDll();
/*
if (Direct3DCreate9_fn!=NULL)
{
RetourFunc((BYTE*) GetProcAddress( gl_hOriginalDll, "Direct3DCreate9"), (BYTE*)Direct3DCreate9_fn, 5);
Direct3DCreate9_fn = (Direct3DCreate9_type) GetProcAddress( gl_hOriginalDll, "Direct3DCreate9");
}
*/
RetourFunc((BYTE*)GetProcAddress(gl_hOriginalDll, "Direct3DCreate9Ex"), (BYTE*)Direct3DCreate9Ex_fn, 7);
Direct3DCreate9Ex_fn = (Direct3DCreate9Ex_type)GetProcAddress(gl_hOriginalDll, "Direct3DCreate9Ex");
// END
IDirect3D9Ex* pIDirect3D9Ex_orig = nullptr;
HRESULT ret;
if (Direct3DCreate9Ex_fn) {
ret = Direct3DCreate9Ex_fn(SDKVersion, &pIDirect3D9Ex_orig); //creating the original IDirect3D9 object
}
else {
return D3DERR_NOTAVAILABLE;
}
if (ret != S_OK) {
return ret;
}
uMod_IDirect3D9Ex* pIDirect3D9Ex;
if (pIDirect3D9Ex_orig) {
pIDirect3D9Ex = new uMod_IDirect3D9Ex(pIDirect3D9Ex_orig, gl_TextureServer.get()); //creating our uMod_IDirect3D9 object
}
// we detour again
/*
if (Direct3DCreate9_fn!=NULL)
{
Direct3DCreate9_fn = (Direct3DCreate9_type)DetourFunc( (BYTE*) Direct3DCreate9_fn, (BYTE*)uMod_Direct3DCreate9,5);
}
*/
Direct3DCreate9Ex_fn = static_cast<Direct3DCreate9Ex_type>(DetourFunc((BYTE*)Direct3DCreate9Ex_fn, (BYTE*)uMod_Direct3DCreate9Ex, 7));
ppD3D = (IDirect3D9Ex**)&pIDirect3D9Ex; //return our object instead of the "real one"
return ret;
}
bool HookThisProgram(char* ret)
{
char Game[MAX_PATH];
GetModuleFileName(GetModuleHandle(nullptr), Game, MAX_PATH); //ask for name and path of this executable
// we inject directly
strcpy(ret, Game);
return true;
}
void* DetourFunc(BYTE* src, const BYTE* dst, const int len)
{
auto jmp = static_cast<BYTE*>(malloc(len + 5));
DWORD dwback = 0;
VirtualProtect(jmp, len + 5, PAGE_EXECUTE_READWRITE, &dwback); //This is the addition needed for Windows 7 RC
VirtualProtect(src, len, PAGE_READWRITE, &dwback);
memcpy(jmp, src, len);
jmp += len;
jmp[0] = 0xE9;
*(DWORD*)(jmp + 1) = static_cast<DWORD>(src + len - jmp) - 5;
memset(src, 0x90, len);
src[0] = 0xE9;
*(DWORD*)(src + 1) = static_cast<DWORD>(dst - src) - 5;
VirtualProtect(src, len, dwback, &dwback);
return jmp - len;
}
bool RetourFunc(BYTE* src, BYTE* restore, const int len)
{
DWORD dwback;
if (!VirtualProtect(src, len, PAGE_READWRITE, &dwback)) { return false; }
if (!memcpy(src, restore, len)) { return false; }
restore[0] = 0xE9;
*(DWORD*)(restore + 1) = static_cast<DWORD>(src - restore) - 5;
if (!VirtualProtect(src, len, dwback, &dwback)) { return false; }
return true;
}
+4 -5
View File
@@ -1,14 +1,13 @@
#include "uMod_Main.h"
#include "Main.h"
#ifndef PRE_MESSAGE
#define PRE_MESSAGE "uMod_IDirect3D9"
#endif
uMod_IDirect3D9::uMod_IDirect3D9(IDirect3D9* pOriginal, uMod_TextureServer* server)
uMod_IDirect3D9::uMod_IDirect3D9(IDirect3D9* pOriginal)
{
Message(PRE_MESSAGE "::" PRE_MESSAGE "( %p, %p): %p\n", pOriginal, server, this);
Message(PRE_MESSAGE "::" PRE_MESSAGE " (%p): %p\n", pOriginal, this);
m_pIDirect3D9 = pOriginal;
uMod_Server = server;
}
uMod_IDirect3D9::~uMod_IDirect3D9()
@@ -126,7 +125,7 @@ HRESULT __stdcall uMod_IDirect3D9::CreateDevice(UINT Adapter, D3DDEVTYPE DeviceT
if (pPresentationParameters != nullptr) {
count = pPresentationParameters->BackBufferCount;
}
const auto pIDirect3DDevice9 = new uMod_IDirect3DDevice9(*ppReturnedDeviceInterface, uMod_Server, count);
const auto pIDirect3DDevice9 = new uMod_IDirect3DDevice9(*ppReturnedDeviceInterface, count);
// store our pointer (the fake one) for returning it to the calling program
*ppReturnedDeviceInterface = pIDirect3DDevice9;
+2 -2
View File
@@ -1,4 +1,4 @@
#include "uMod_Main.h"
#include "Main.h"
#define IDirect3D9 IDirect3D9Ex
#define uMod_IDirect3D9 uMod_IDirect3D9Ex
@@ -19,7 +19,7 @@ HRESULT __stdcall uMod_IDirect3D9Ex::CreateDeviceEx(UINT Adapter, D3DDEVTYPE Dev
if (pPresentationParameters != nullptr) {
count = pPresentationParameters->BackBufferCount;
}
const auto pIDirect3DDevice9Ex = new uMod_IDirect3DDevice9Ex(*ppReturnedDeviceInterface, uMod_Server, count);
const auto pIDirect3DDevice9Ex = new uMod_IDirect3DDevice9Ex(*ppReturnedDeviceInterface, count);
// store our pointer (the fake one) for returning it to the calling program
*ppReturnedDeviceInterface = pIDirect3DDevice9Ex;
+11 -83
View File
@@ -1,4 +1,4 @@
#include "uMod_Main.h"
#include "Main.h"
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DCubeTexture9::QueryInterface(REFIID riid, void** ppvObj)
@@ -100,7 +100,7 @@ ULONG APIENTRY uMod_IDirect3DCubeTexture9::Release()
}
}
delete(this);
delete this;
}
return count;
}
@@ -235,19 +235,16 @@ HRESULT APIENTRY uMod_IDirect3DCubeTexture9::UnlockRect(D3DCUBEMAP_FACES FaceTyp
int uMod_IDirect3DCubeTexture9::GetHash(MyTypeHash& hash)
HashType uMod_IDirect3DCubeTexture9::GetHash() const
{
hash = 0u;
if (FAKE) {
return RETURN_BAD_ARGUMENT;
return 0;
}
IDirect3DCubeTexture9* pTexture = m_D3Dtex;
if (CrossRef_D3Dtex != nullptr) {
pTexture = CrossRef_D3Dtex->m_D3Dtex;
}
//IDirect3DSurface9 *pOffscreenSurface = NULL;
//IDirect3DCubeTexture9 *pOffscreenTexture = NULL;
IDirect3DSurface9* pResolvedSurface = nullptr;
D3DLOCKED_RECT d3dlr;
D3DSURFACE_DESC desc;
@@ -255,98 +252,29 @@ int uMod_IDirect3DCubeTexture9::GetHash(MyTypeHash& hash)
if (pTexture->GetLevelDesc(0, &desc) != D3D_OK) //get the format and the size of the texture
{
Message("uMod_IDirect3DCubeTexture9::GetHash() Failed: GetLevelDesc \n");
return RETURN_GetLevelDesc_FAILED;
return 0;
}
Message("uMod_IDirect3DCubeTexture9::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_IDirect3DCubeTexture9::GetHash() (D3DPOOL_DEFAULT)\n");
IDirect3DSurface9 *pSurfaceLevel_orig = NULL;
if (pTexture->GetSurfaceLevel( 0, &pSurfaceLevel_orig)!=D3D_OK)
if (pTexture->LockRect(D3DCUBEMAP_FACE_POSITIVE_X, 0, &d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK)
{
Message("uMod_IDirect3DCubeTexture9::GetHash() Failed: GetSurfaceLevel 1 (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED);
}
if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
{
//Message("uMod_IDirect3DCubeTexture9::GetHash() MultiSampleType\n");
if (D3D_OK!=m_D3Ddev->CreateRenderTarget( desc.Width, desc.Height, desc.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pResolvedSurface, NULL ))
{
pSurfaceLevel_orig->Release();
Message("uMod_IDirect3DCubeTexture9::GetHash() Failed: CreateRenderTarget (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED);
}
if (D3D_OK!=m_D3Ddev->StretchRect( pSurfaceLevel_orig, NULL, pResolvedSurface, NULL, D3DTEXF_NONE ))
{
pSurfaceLevel_orig->Release();
Message("uMod_IDirect3DCubeTexture9::GetHash() Failed: StretchRect (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED);
}
pSurfaceLevel_orig = pResolvedSurface;
}
if (D3D_OK!=m_D3Ddev->CreateOffscreenPlainSurface( desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pOffscreenSurface, NULL))
{
pSurfaceLevel_orig->Release();
if (pResolvedSurface!=NULL) pResolvedSurface->Release();
Message("uMod_IDirect3DCubeTexture9::GetHash() Failed: CreateOffscreenPlainSurface (D3DPOOL_DEFAULT)\n");
return RETURN_TEXTURE_NOT_LOADED);
}
if (D3D_OK!=m_D3Ddev->GetRenderTargetData( pSurfaceLevel_orig, pOffscreenSurface))
{
pSurfaceLevel_orig->Release();
if (pResolvedSurface!=NULL) pResolvedSurface->Release();
pOffscreenSurface->Release();
Message("uMod_IDirect3DCubeTexture9::GetHash() Failed: GetRenderTargetData (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED);
}
pSurfaceLevel_orig->Release();
if (pOffscreenSurface->LockRect( &d3dlr, NULL, D3DLOCK_READONLY)!=D3D_OK)
{
if (pResolvedSurface!=NULL) pResolvedSurface->Release();
pOffscreenSurface->Release();
Message("uMod_IDirect3DCubeTexture9::GetHash() Failed: LockRect (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED);
}
}
else
*/
if (pTexture->LockRect(D3DCUBEMAP_FACE_POSITIVE_X, 0, &d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) {
Message("uMod_IDirect3DCubeTexture9::GetHash() Failed: LockRect 1\n");
if (pTexture->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_X, 0, &pResolvedSurface) != D3D_OK) {
Message("uMod_IDirect3DCubeTexture9::GetHash() Failed: GetSurfaceLevel\n");
return RETURN_LockRect_FAILED;
return 0;
}
if (pResolvedSurface->LockRect(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) {
pResolvedSurface->Release();
Message("uMod_IDirect3DCubeTexture9::GetHash() Failed: LockRect 2\n");
return RETURN_LockRect_FAILED;
return 0;
}
}
const int size = (GetBitsFromFormat(desc.Format) * desc.Width * desc.Height) / 8;
const auto hash = GetCRC32(static_cast<char*>(d3dlr.pBits), size); //calculate the crc32 of the texture
hash = GetCRC32(static_cast<char*>(d3dlr.pBits), size); //calculate the crc32 of the texture
/*
if (pOffscreenSurface!=NULL)
{
pOffscreenSurface->UnlockRect();
pOffscreenSurface->Release();
//pOffscreenTexture->Release();
if (pResolvedSurface!=NULL) pResolvedSurface->Release();
}
else
*/
// Only release surfaces after we're finished with d3dlr
if (pResolvedSurface != nullptr) {
pResolvedSurface->UnlockRect();
pResolvedSurface->Release();
@@ -356,5 +284,5 @@ int uMod_IDirect3DCubeTexture9::GetHash(MyTypeHash& hash)
}
Message("uMod_IDirect3DCubeTexture9::GetHash() %#lX (%d %d) %d = %d\n", hash, desc.Width, desc.Height, desc.Format, size);
return RETURN_OK;
return hash;
}
+12 -20
View File
@@ -1,4 +1,4 @@
#include "uMod_Main.h"
#include "Main.h"
#ifndef RETURN_QueryInterface
#define RETURN_QueryInterface 0x01000000L
@@ -24,7 +24,6 @@ int uMod_IDirect3DDevice9::CreateSingleTexture()
}
LastCreatedTexture = nullptr; // set LastCreatedTexture to NULL, cause LastCreatedTexture is equal SingleTexture
SingleTexture->FAKE = true; //this is no texture created from by game
SingleTexture->Reference = -2;
}
{
@@ -54,7 +53,6 @@ int uMod_IDirect3DDevice9::CreateSingleTexture()
}
LastCreatedVolumeTexture = nullptr; // set LastCreatedTexture to NULL, cause LastCreatedTexture is equal SingleTexture
SingleVolumeTexture->FAKE = true; //this is no texture created from by game
SingleVolumeTexture->Reference = -2;
}
{
@@ -83,7 +81,6 @@ int uMod_IDirect3DDevice9::CreateSingleTexture()
}
LastCreatedCubeTexture = nullptr; // set LastCreatedTexture to NULL, cause LastCreatedTexture is equal SingleTexture
SingleCubeTexture->FAKE = true; //this is no texture created from by game
SingleCubeTexture->Reference = -2;
}
{
@@ -109,15 +106,15 @@ int uMod_IDirect3DDevice9::CreateSingleTexture()
return RETURN_OK;
}
uMod_IDirect3DDevice9::uMod_IDirect3DDevice9(IDirect3DDevice9* pOriginal, uMod_TextureServer* server, int back_buffer_count)
uMod_IDirect3DDevice9::uMod_IDirect3DDevice9(IDirect3DDevice9* pOriginal, int back_buffer_count)
{
Message(PRE_MESSAGE "::" PRE_MESSAGE "( %p, %p): %p\n", pOriginal, server, this);
Message(PRE_MESSAGE "::" PRE_MESSAGE " (%p): %p\n", pOriginal, this);
BackBufferCount = back_buffer_count;
NormalRendering = true;
uMod_Server = server;
uMod_Client = new uMod_TextureClient(uMod_Server, this); //get a new texture client for this device
uMod_Client = new TextureClient(this); //get a new texture client for this device
uMod_Client->Initialize();
LastCreatedTexture = nullptr;
LastCreatedVolumeTexture = nullptr;
@@ -422,12 +419,10 @@ HRESULT uMod_IDirect3DDevice9::UpdateTexture(IDirect3DBaseTexture9* pSourceTextu
uMod_IDirect3DCubeTexture9* pSourceCube = nullptr;
IDirect3DBaseTexture9* cpy;
if (pSourceTexture != nullptr) {
long int ret = pSourceTexture->QueryInterface(IID_IDirect3D9, (void**)&cpy);
switch (ret) {
switch (pSourceTexture->QueryInterface(IID_IDirect3D9, (void**)&cpy)) {
case 0x01000000L: {
MyTypeHash hash;
pSource = static_cast<uMod_IDirect3DTexture9*>(pSourceTexture);
if (pSource->GetHash(hash) == RETURN_OK) {
if (const auto hash = pSource->GetHash()) {
if (hash != pSource->Hash) // this hash has changed !!
{
pSource->Hash = hash;
@@ -451,9 +446,8 @@ HRESULT uMod_IDirect3DDevice9::UpdateTexture(IDirect3DBaseTexture9* pSourceTextu
break;
}
case 0x01000001L: {
MyTypeHash hash;
pSourceVolume = static_cast<uMod_IDirect3DVolumeTexture9*>(pSourceTexture);
if (pSourceVolume->GetHash(hash) == RETURN_OK) {
if (const auto hash = pSource->GetHash()) {
if (hash != pSourceVolume->Hash) // this hash has changed !!
{
pSourceVolume->Hash = hash;
@@ -477,9 +471,8 @@ HRESULT uMod_IDirect3DDevice9::UpdateTexture(IDirect3DBaseTexture9* pSourceTextu
break;
}
case 0x01000002L: {
MyTypeHash hash;
pSourceCube = static_cast<uMod_IDirect3DCubeTexture9*>(pSourceTexture);
if (pSourceCube->GetHash(hash) == RETURN_OK) {
if (const auto hash = pSourceCube->GetHash()) {
if (hash != pSourceCube->Hash) // this hash has changed !!
{
pSourceCube->Hash = hash;
@@ -509,10 +502,9 @@ HRESULT uMod_IDirect3DDevice9::UpdateTexture(IDirect3DBaseTexture9* pSourceTextu
if (pDestinationTexture != nullptr) {
long int ret = pSourceTexture->QueryInterface(IID_IDirect3D9, (void**)&cpy);
switch (ret) {
switch (pSourceTexture->QueryInterface(IID_IDirect3D9, (void**)&cpy)) {
case 0x01000000L: {
auto pDest = static_cast<uMod_IDirect3DTexture9*>(pDestinationTexture);
const auto pDest = static_cast<uMod_IDirect3DTexture9*>(pDestinationTexture);
if (pSource != nullptr && pDest->Hash != pSource->Hash) {
pDest->Hash = pSource->Hash; // take over the hash
@@ -532,7 +524,7 @@ HRESULT uMod_IDirect3DDevice9::UpdateTexture(IDirect3DBaseTexture9* pSourceTextu
break;
}
case 0x01000001L: {
auto pDest = static_cast<uMod_IDirect3DVolumeTexture9*>(pDestinationTexture);
const auto pDest = static_cast<uMod_IDirect3DVolumeTexture9*>(pDestinationTexture);
if (pSourceVolume != nullptr && pDest->Hash != pSourceVolume->Hash) {
pDest->Hash = pSourceVolume->Hash; // take over the hash
+1 -1
View File
@@ -1,4 +1,4 @@
#include "uMod_Main.h"
#include "Main.h"
#define uMod_IDirect3DDevice9 uMod_IDirect3DDevice9Ex
#define IDirect3DDevice9 IDirect3DDevice9Ex
+16 -20
View File
@@ -1,4 +1,4 @@
#include "uMod_Main.h"
#include "Main.h"
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DTexture9::QueryInterface(REFIID riid, void** ppvObj)
@@ -100,7 +100,7 @@ ULONG APIENTRY uMod_IDirect3DTexture9::Release()
}
}
delete(this);
delete this;
}
Message("uMod_IDirect3DTexture9::Release() end: %p\n", this);
@@ -236,12 +236,9 @@ HRESULT APIENTRY uMod_IDirect3DTexture9::AddDirtyRect(CONST RECT* pDirtyRect)
}
int uMod_IDirect3DTexture9::GetHash(MyTypeHash& hash)
HashType uMod_IDirect3DTexture9::GetHash() const
{
hash = 0u;
if (FAKE) {
return RETURN_BAD_ARGUMENT;
}
ASSERT(!FAKE);
IDirect3DTexture9* pTexture = m_D3Dtex;
if (CrossRef_D3Dtex != nullptr) {
pTexture = CrossRef_D3Dtex->m_D3Dtex;
@@ -256,7 +253,7 @@ int uMod_IDirect3DTexture9::GetHash(MyTypeHash& hash)
if (pTexture->GetLevelDesc(0, &desc) != D3D_OK) //get the format and the size of the texture
{
Message("uMod_IDirect3DTexture9::GetHash() Failed: GetLevelDesc \n");
return RETURN_GetLevelDesc_FAILED;
return 0;
}
Message("uMod_IDirect3DTexture9::GetHash() (%d %d) %d\n", desc.Width, desc.Height, desc.Format);
@@ -269,7 +266,7 @@ int uMod_IDirect3DTexture9::GetHash(MyTypeHash& hash)
IDirect3DSurface9* pSurfaceLevel_orig = nullptr;
if (pTexture->GetSurfaceLevel(0, &pSurfaceLevel_orig) != D3D_OK) {
Message("uMod_IDirect3DTexture9::GetHash() Failed: GetSurfaceLevel 1 (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED;
return 0;
}
if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) {
@@ -277,12 +274,12 @@ int uMod_IDirect3DTexture9::GetHash(MyTypeHash& hash)
if (D3D_OK != m_D3Ddev->CreateRenderTarget(desc.Width, desc.Height, desc.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pResolvedSurface, nullptr)) {
pSurfaceLevel_orig->Release();
Message("uMod_IDirect3DTexture9::GetHash() Failed: CreateRenderTarget (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED;
return 0;
}
if (D3D_OK != m_D3Ddev->StretchRect(pSurfaceLevel_orig, nullptr, pResolvedSurface, nullptr, D3DTEXF_NONE)) {
pSurfaceLevel_orig->Release();
Message("uMod_IDirect3DTexture9::GetHash() Failed: StretchRect (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED;
return 0;
}
pSurfaceLevel_orig = pResolvedSurface;
@@ -294,7 +291,7 @@ int uMod_IDirect3DTexture9::GetHash(MyTypeHash& hash)
pResolvedSurface->Release();
}
Message("uMod_IDirect3DTexture9::GetHash() Failed: CreateOffscreenPlainSurface (D3DPOOL_DEFAULT)\n");
return RETURN_TEXTURE_NOT_LOADED;
return 0;
}
if (D3D_OK != m_D3Ddev->GetRenderTargetData(pSurfaceLevel_orig, pOffscreenSurface)) {
@@ -304,7 +301,7 @@ int uMod_IDirect3DTexture9::GetHash(MyTypeHash& hash)
}
pOffscreenSurface->Release();
Message("uMod_IDirect3DTexture9::GetHash() Failed: GetRenderTargetData (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED;
return 0;
}
pSurfaceLevel_orig->Release();
@@ -314,26 +311,26 @@ int uMod_IDirect3DTexture9::GetHash(MyTypeHash& hash)
}
pOffscreenSurface->Release();
Message("uMod_IDirect3DTexture9::GetHash() Failed: LockRect (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED;
return 0;
}
}
else if (pTexture->LockRect(0, &d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) {
Message("uMod_IDirect3DTexture9::GetHash() Failed: LockRect 1\n");
if (pTexture->GetSurfaceLevel(0, &pResolvedSurface) != D3D_OK) {
Message("uMod_IDirect3DTexture9::GetHash() Failed: GetSurfaceLevel\n");
return RETURN_LockRect_FAILED;
return 0;
}
if (pResolvedSurface->LockRect(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) {
pResolvedSurface->Release();
Message("uMod_IDirect3DTexture9::GetHash() Failed: LockRect 2\n");
return RETURN_LockRect_FAILED;
return 0;
}
}
const int size = (GetBitsFromFormat(desc.Format) * desc.Width * desc.Height) / 8;
const auto hash = GetCRC32(static_cast<char*>(d3dlr.pBits), size); //calculate the crc32 of the texture
hash = GetCRC32(static_cast<char*>(d3dlr.pBits), size); //calculate the crc32 of the texture
// Only release surfaces after we're finished with d3dlr
if (pOffscreenSurface != nullptr) {
pOffscreenSurface->UnlockRect();
pOffscreenSurface->Release();
@@ -348,7 +345,6 @@ int uMod_IDirect3DTexture9::GetHash(MyTypeHash& hash)
else {
pTexture->UnlockRect(0);
}
Message("uMod_IDirect3DTexture9::GetHash() %#lX (%d %d) %d = %d\n", hash, desc.Width, desc.Height, desc.Format, size);
return RETURN_OK;
return hash;
}
+12 -110
View File
@@ -1,4 +1,4 @@
#include "uMod_Main.h"
#include "Main.h"
HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::QueryInterface(REFIID riid, void** ppvObj)
{
@@ -99,7 +99,7 @@ ULONG APIENTRY uMod_IDirect3DVolumeTexture9::Release()
}
}
delete(this);
delete this;
}
return count;
}
@@ -235,19 +235,16 @@ HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::UnlockBox(UINT Level)
}
int uMod_IDirect3DVolumeTexture9::GetHash(MyTypeHash& hash)
HashType uMod_IDirect3DVolumeTexture9::GetHash() const
{
hash = 0u;
if (FAKE) {
return RETURN_BAD_ARGUMENT;
return 0;
}
IDirect3DVolumeTexture9* pTexture = m_D3Dtex;
if (CrossRef_D3Dtex != nullptr) {
pTexture = CrossRef_D3Dtex->m_D3Dtex;
}
//IDirect3DVolume9 *pOffscreenSurface = NULL;
//IDirect3DVolumeTexture9 *pOffscreenTexture = NULL;
IDirect3DVolume9* pResolvedSurface = nullptr;
D3DLOCKED_BOX d3dlr;
D3DVOLUME_DESC desc;
@@ -255,124 +252,29 @@ int uMod_IDirect3DVolumeTexture9::GetHash(MyTypeHash& hash)
if (pTexture->GetLevelDesc(0, &desc) != D3D_OK) //get the format and the size of the texture
{
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: GetLevelDesc \n");
return RETURN_GetLevelDesc_FAILED;
return 0;
}
Message("uMod_IDirect3DVolumeTexture9::GetHash() (%d %d %d) %d\n", desc.Width, desc.Height, desc.Depth, desc.Format);
/*
if (desc.Pool==D3DPOOL_DEFAULT) //get the raw data of the texture
{
//Message("uMod_IDirect3DVolumeTexture9::GetHash() (D3DPOOL_DEFAULT)\n");
IDirect3DSurface9 *pSurfaceLevel_orig = NULL;
if (pTexture->GetSurfaceLevel( 0, &pSurfaceLevel_orig)!=D3D_OK)
{
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: GetSurfaceLevel 1 (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED);
}
/*
if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
{
//Message("uMod_IDirect3DVolumeTexture9::GetHash() MultiSampleType\n");
if (D3D_OK!=m_D3Ddev->CreateRenderTarget( desc.Width, desc.Height, desc.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pResolvedSurface, NULL ))
{
pSurfaceLevel_orig->Release();
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: CreateRenderTarget (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED);
}
if (D3D_OK!=m_D3Ddev->StretchRect( pSurfaceLevel_orig, NULL, pResolvedSurface, NULL, D3DTEXF_NONE ))
{
pSurfaceLevel_orig->Release();
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: StretchRect (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED);
}
pSurfaceLevel_orig = pResolvedSurface;
}
*/
//CreateTexture(8, 8, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, (IDirect3DVolumeTexture9**) &SingleTexture, NULL)
/*
if (D3D_OK!=m_D3Ddev->CreateTexture( desc.Width, desc.Height, 1, 0, desc.Format, D3DPOOL_SYSTEMMEM, &pOffscreenTexture, NULL))
{
pSurfaceLevel_orig->Release();
if (pResolvedSurface!=NULL) pResolvedSurface->Release();
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: CreateTexture (D3DPOOL_DEFAULT)\n");
return RETURN_TEXTURE_NOT_LOADED);
}
if (pOffscreenTexture->GetSurfaceLevel( 0, &pOffscreenSurface)!=D3D_OK)
{
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: GetSurfaceLevel 2 (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED);
}
if (D3D_OK!=m_D3Ddev->GetRenderTargetData( pSurfaceLevel_orig, pOffscreenSurface))
{
pSurfaceLevel_orig->Release();
if (pResolvedSurface!=NULL) pResolvedSurface->Release();
pOffscreenSurface->Release();
pOffscreenTexture->Release();
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: GetRenderTargetData (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED);
}
pSurfaceLevel_orig->Release();
if (pOffscreenSurface->LockRect( &d3dlr, NULL, D3DLOCK_READONLY)!=D3D_OK)
{
if (pResolvedSurface!=NULL) pResolvedSurface->Release();
pOffscreenSurface->Release();
pOffscreenTexture->Release();
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: LockRect (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED);
}
*/
/*
if (D3D_OK!=m_D3Ddev->CreateOffscreenPlainSurface( desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pOffscreenSurface, NULL))
{
pSurfaceLevel_orig->Release();
if (pResolvedSurface!=NULL) pResolvedSurface->Release();
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: CreateOffscreenPlainSurface (D3DPOOL_DEFAULT)\n");
return RETURN_TEXTURE_NOT_LOADED);
}
if (D3D_OK!=m_D3Ddev->GetRenderTargetData( pSurfaceLevel_orig, pOffscreenSurface))
{
pSurfaceLevel_orig->Release();
if (pResolvedSurface!=NULL) pResolvedSurface->Release();
pOffscreenSurface->Release();
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: GetRenderTargetData (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED);
}
pSurfaceLevel_orig->Release();
if (pOffscreenSurface->LockRect( &d3dlr, NULL, D3DLOCK_READONLY)!=D3D_OK)
{
if (pResolvedSurface!=NULL) pResolvedSurface->Release();
pOffscreenSurface->Release();
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: LockRect (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED);
}
}
else
*/
if (pTexture->LockBox(0, &d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) {
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: LockRect 1\n");
if (pTexture->GetVolumeLevel(0, &pResolvedSurface) != D3D_OK) {
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: GetSurfaceLevel\n");
return RETURN_LockRect_FAILED;
return 0;
}
if (pResolvedSurface->LockBox(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) {
pResolvedSurface->Release();
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: LockRect 2\n");
return RETURN_LockRect_FAILED;
return 0;
}
}
const int size = (GetBitsFromFormat(desc.Format) * desc.Width * desc.Height * desc.Depth) / 8;
const auto hash = GetCRC32(static_cast<char*>(d3dlr.pBits), size); //calculate the crc32 of the texture
hash = GetCRC32(static_cast<char*>(d3dlr.pBits), size); //calculate the crc32 of the texture
// Only release surfaces after we're finished with d3dlr
if (pResolvedSurface != nullptr) {
pResolvedSurface->UnlockBox();
pResolvedSurface->Release();
@@ -382,5 +284,5 @@ int uMod_IDirect3DVolumeTexture9::GetHash(MyTypeHash& hash)
}
Message("uMod_IDirect3DVolumeTexture9::GetHash() %#lX (%d %d) %d = %d\n", hash, desc.Width, desc.Height, desc.Format, size);
return RETURN_OK;
return hash;
}
-829
View File
@@ -1,829 +0,0 @@
#include "uMod_Main.h"
uMod_TextureClient::uMod_TextureClient(uMod_TextureServer* server, IDirect3DDevice9* device)
{
Message("uMod_TextureClient::uMod_TextureClient(): %p\n", this);
Server = server;
D3D9Device = device;
NumberToMod = 0;
FileToMod = nullptr;
if (Server != nullptr) {
if (Server->AddClient(this, &FileToMod, &NumberToMod)) {
Server = nullptr;
NumberToMod = 0;
FileToMod = nullptr;
}
else {
for (int i = 0; i < NumberToMod; i++) {
FileToMod[i].NumberOfTextures = 0;
FileToMod[i].Textures = nullptr;
}
}
}
Mutex = CreateMutex(nullptr, false, nullptr);
Update = nullptr;
NumberOfUpdate = -1;
FontColour = D3DCOLOR_ARGB(255, 255, 0, 0);
TextureColour = D3DCOLOR_ARGB(255, 0, 255, 0);
}
uMod_TextureClient::~uMod_TextureClient()
{
Message("uMod_TextureClient::~uMod_TextureClient(): %p\n", this);
if (Mutex != nullptr) {
CloseHandle(Mutex);
}
delete [] Update;
if (FileToMod != nullptr) {
for (int i = 0; i < NumberToMod; i++) {
delete [] FileToMod[i].Textures;
}
delete [] FileToMod;
}
}
int uMod_TextureClient::AddTexture(uMod_IDirect3DTexture9* pTexture)
{
void* cpy;
const long ret = D3D9Device->QueryInterface(IID_IDirect3DTexture9, &cpy);
if (ret == 0x01000000L) {
static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->SetLastCreatedTexture(nullptr); //this texture must no be added twice
}
else {
static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->SetLastCreatedTexture(nullptr); //this texture must no be added twice
}
if (pTexture->FAKE) {
return RETURN_OK; // this is a fake texture
}
Message("uMod_TextureClient::AddTexture( %p): %p (thread: %p)\n", pTexture, this, GetCurrentThreadId());
MyTypeHash hash;
if (const int ret = pTexture->GetHash(hash)) {
return ret;
}
pTexture->Hash = hash;
if (gl_ErrorState & uMod_ERROR_FATAL) {
return RETURN_FATAL_ERROR;
}
OriginalTextures.Add(pTexture); // add the texture to the list of original texture
return LookUpToMod(pTexture); // check if this texture should be modded
}
int uMod_TextureClient::AddTexture(uMod_IDirect3DVolumeTexture9* pTexture)
{
void* cpy;
const long ret = D3D9Device->QueryInterface(IID_IDirect3DTexture9, &cpy);
if (ret == 0x01000000L) {
static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->SetLastCreatedVolumeTexture(nullptr); //this texture must no be added twice
}
else {
static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->SetLastCreatedVolumeTexture(nullptr); //this texture must no be added twice
}
if (pTexture->FAKE) {
return RETURN_OK; // this is a fake texture
}
Message("uMod_TextureClient::AddTexture( Volume: %p): %p (thread: %p)\n", pTexture, this, GetCurrentThreadId());
MyTypeHash hash;
if (const int ret = pTexture->GetHash(hash)) {
return ret;
}
pTexture->Hash = hash;
if (gl_ErrorState & uMod_ERROR_FATAL) {
return RETURN_FATAL_ERROR;
}
OriginalVolumeTextures.Add(pTexture); // add the texture to the list of original texture
return LookUpToMod(pTexture); // check if this texture should be modded
}
int uMod_TextureClient::AddTexture(uMod_IDirect3DCubeTexture9* pTexture)
{
void* cpy;
const long ret = D3D9Device->QueryInterface(IID_IDirect3DTexture9, &cpy);
if (ret == 0x01000000L) {
static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->SetLastCreatedCubeTexture(nullptr); //this texture must no be added twice
}
else {
static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->SetLastCreatedCubeTexture(nullptr); //this texture must no be added twice
}
if (pTexture->FAKE) {
return RETURN_OK; // this is a fake texture
}
Message("uMod_TextureClient::AddTexture( Cube: %p): %p (thread: %p)\n", pTexture, this, GetCurrentThreadId());
MyTypeHash hash;
if (const int ret = pTexture->GetHash(hash)) {
return ret;
}
pTexture->Hash = hash;
if (gl_ErrorState & uMod_ERROR_FATAL) {
return RETURN_FATAL_ERROR;
}
OriginalCubeTextures.Add(pTexture); // add the texture to the list of original texture
return LookUpToMod(pTexture); // check if this texture should be modded
}
int uMod_TextureClient::RemoveTexture(uMod_IDirect3DTexture9* pTexture) // is called from a texture, if it is finally released
{
Message("uMod_TextureClient::RemoveTexture( %p, %#lX): %p\n", pTexture, pTexture->Hash, this);
if (gl_ErrorState & uMod_ERROR_FATAL) {
return RETURN_FATAL_ERROR;
}
if (pTexture->FAKE) {
// we need to set the corresponding FileToMod[X].pTexture to NULL, to avoid a link to a non existing texture object
const int ref = pTexture->Reference;
if (ref >= 0 && ref < NumberToMod) {
for (int i = 0; i < FileToMod[ref].NumberOfTextures; i++) {
if (FileToMod[ref].Textures[i] == pTexture) {
FileToMod[ref].NumberOfTextures--;
for (int j = i; j < FileToMod[ref].NumberOfTextures; j++) {
FileToMod[ref].Textures[j] = FileToMod[ref].Textures[j + 1];
}
FileToMod[ref].Textures[FileToMod[ref].NumberOfTextures] = nullptr;
break;
}
}
}
}
else {
return OriginalTextures.Remove(pTexture); //remove this texture form the list
}
return RETURN_OK;
}
int uMod_TextureClient::RemoveTexture(uMod_IDirect3DVolumeTexture9* pTexture) // is called from a texture, if it is finally released
{
Message("uMod_TextureClient::RemoveTexture( Volume %p, %#lX): %p\n", pTexture, pTexture->Hash, this);
if (gl_ErrorState & uMod_ERROR_FATAL) {
return RETURN_FATAL_ERROR;
}
if (pTexture->FAKE) {
// we need to set the corresponding FileToMod[X].pTexture to NULL, to avoid a link to a non existing texture object
const int ref = pTexture->Reference;
if (ref >= 0 && ref < NumberToMod) {
for (int i = 0; i < FileToMod[ref].NumberOfTextures; i++) {
if (FileToMod[ref].Textures[i] == pTexture) {
FileToMod[ref].NumberOfTextures--;
for (int j = i; j < FileToMod[ref].NumberOfTextures; j++) {
FileToMod[ref].Textures[j] = FileToMod[ref].Textures[j + 1];
}
FileToMod[ref].Textures[FileToMod[ref].NumberOfTextures] = nullptr;
break;
}
}
}
}
else {
return OriginalVolumeTextures.Remove(pTexture); //remove this texture form the list
}
return RETURN_OK;
}
int uMod_TextureClient::RemoveTexture(uMod_IDirect3DCubeTexture9* pTexture) // is called from a texture, if it is finally released
{
Message("uMod_TextureClient::RemoveTexture( Cube %p, %#lX): %p\n", pTexture, pTexture->Hash, this);
if (gl_ErrorState & uMod_ERROR_FATAL) {
return RETURN_FATAL_ERROR;
}
if (pTexture->FAKE) {
// we need to set the corresponding FileToMod[X].pTexture to NULL, to avoid a link to a non existing texture object
const int ref = pTexture->Reference;
if (ref >= 0 && ref < NumberToMod) {
for (int i = 0; i < FileToMod[ref].NumberOfTextures; i++) {
if (FileToMod[ref].Textures[i] == pTexture) {
FileToMod[ref].NumberOfTextures--;
for (int j = i; j < FileToMod[ref].NumberOfTextures; j++) {
FileToMod[ref].Textures[j] = FileToMod[ref].Textures[j + 1];
}
FileToMod[ref].Textures[FileToMod[ref].NumberOfTextures] = nullptr;
break;
}
}
}
}
else {
return OriginalCubeTextures.Remove(pTexture); //remove this texture form the list
}
return RETURN_OK;
}
int uMod_TextureClient::AddUpdate(TextureFileStruct* update, int number) //client must delete the update array
{
Message("AddUpdate( %p, %d): %p\n", update, number, this);
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_TEXTURE;
return ret;
}
delete [] Update;
Update = update;
NumberOfUpdate = number;
return UnlockMutex();
}
int uMod_TextureClient::MergeUpdate()
{
if (NumberOfUpdate < 0) { return RETURN_OK; }
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_TEXTURE;
return ret;
}
Message("MergeUpdate(): %p\n", this);
for (int i = 0; i < NumberOfUpdate; i++) {
Update[i].NumberOfTextures = 0;
Update[i].Textures = nullptr;
} // this is already done, but safety comes first ^^
int pos_old = 0;
int pos_new = 0;
int* to_lookup = nullptr;
if (NumberOfUpdate > 0) {
to_lookup = new int[NumberOfUpdate];
}
int num_to_lookup = 0;
/*
* FileToMod contains the old files (textures) which should replace the target textures (if they are loaded by the game)
* Update contains the new files (textures) which should replace the target textures (if they are loaded by the game)
*
* Both arrays (FileToMod and Update) are sorted according to their hash values.
*
* First we go through both arrays linearly and
* 1) take over the old entry if the hash is the same,
* 2) release old fake texture (if target texture exist and is not in the Update)
* 3) or mark newly added fake texture (if they are not in FileToMod)
*/
while (pos_old < NumberToMod && pos_new < NumberOfUpdate) {
if (FileToMod[pos_old].Hash > Update[pos_new].Hash) // this fake texture is new
{
to_lookup[num_to_lookup++] = pos_new++; // keep this fake texture in mind, we must search later for it through all original textures
// we increase only the new counter by one
}
else if (FileToMod[pos_old].Hash < Update[pos_new].Hash) // this fake texture is not in the update
{
for (int i = FileToMod[pos_old].NumberOfTextures - 1; i >= 0; i--) {
FileToMod[pos_old].Textures[i]->Release(); // we release the fake textures
}
delete [] FileToMod[pos_old].Textures; // we delete the memory
FileToMod[pos_old].NumberOfTextures = 0;
FileToMod[pos_old].Textures = nullptr;
pos_old++; // we increase only the old counter by one
}
else // the hash value is the same, thus this texture is in the array FileToMod as well as in the array Update
{
if (Update[pos_new].ForceReload) {
if (FileToMod[pos_old].NumberOfTextures > 0) {
Update[pos_new].Textures = new IDirect3DBaseTexture9*[FileToMod[pos_old].NumberOfTextures];
}
for (int i = 0; i < FileToMod[pos_old].NumberOfTextures; i++) {
IDirect3DBaseTexture9* base_texture;
int ret = FileToMod[pos_old].Textures[i]->QueryInterface(IID_IDirect3D9, (void**)&base_texture);
switch (ret) {
case 0x01000000L: {
auto pTexture = static_cast<uMod_IDirect3DTexture9*>(FileToMod[pos_old].Textures[i]);//
uMod_IDirect3DTexture9* pRefTexture = pTexture->CrossRef_D3Dtex;
pTexture->Release();
i--; //after the Release of the old fake texture FileToMod[pos_old].Textures[i] is overwritten by entries with index greater than i
uMod_IDirect3DTexture9* fake_Texture;
if (int ret = LoadTexture(&(Update[pos_new]), &fake_Texture)) {
return ret;
}
if (SwitchTextures(fake_Texture, pRefTexture)) {
Message("MergeUpdate(): textures not switched %#lX\n", pRefTexture->Hash);
fake_Texture->Release();
}
else {
Update[pos_new].Textures[Update[pos_new].NumberOfTextures++] = fake_Texture;
fake_Texture->Reference = pos_new;
}
break;
}
case 0x01000001L: {
auto pTexture = static_cast<uMod_IDirect3DVolumeTexture9*>(FileToMod[pos_old].Textures[i]);//
uMod_IDirect3DVolumeTexture9* pRefTexture = pTexture->CrossRef_D3Dtex;
pTexture->Release();
i--; //after the Release of the old fake texture FileToMod[pos_old].Textures[i] is overwritten by entries with index greater than i
uMod_IDirect3DVolumeTexture9* fake_Texture;
if (int ret = LoadTexture(&(Update[pos_new]), &fake_Texture)) {
return ret;
}
if (SwitchTextures(fake_Texture, pRefTexture)) {
Message("MergeUpdate(): textures not switched %#lX\n", pRefTexture->Hash);
fake_Texture->Release();
}
else {
Update[pos_new].Textures[Update[pos_new].NumberOfTextures++] = fake_Texture;
fake_Texture->Reference = pos_new;
}
break;
}
case 0x01000002L: {
auto pTexture = static_cast<uMod_IDirect3DCubeTexture9*>(FileToMod[pos_old].Textures[i]);//
uMod_IDirect3DCubeTexture9* pRefTexture = pTexture->CrossRef_D3Dtex;
pTexture->Release();
i--; //after the Release of the old fake texture FileToMod[pos_old].Textures[i] is overwritten by entries with index greater than i
uMod_IDirect3DCubeTexture9* fake_Texture;
if (int ret = LoadTexture(&Update[pos_new], &fake_Texture)) {
return ret;
}
if (SwitchTextures(fake_Texture, pRefTexture)) {
Message("MergeUpdate(): textures not switched %#lX\n", pRefTexture->Hash);
fake_Texture->Release();
}
else {
Update[pos_new].Textures[Update[pos_new].NumberOfTextures++] = fake_Texture;
fake_Texture->Reference = pos_new;
}
break;
}
default:
break; // this is no fake texture and QueryInterface failed, because IDirect3DBaseTexture9 object cannot be a IDirect3D9 object ;)
}
}
}
else // the texture might be loaded or not
{
Update[pos_new].NumberOfTextures = FileToMod[pos_old].NumberOfTextures;
Update[pos_new].Textures = FileToMod[pos_old].Textures;
FileToMod[pos_old].NumberOfTextures = 0;
FileToMod[pos_old].Textures = nullptr;
}
// we increase both counters by one
pos_old++;
pos_new++;
}
}
while (pos_old < NumberToMod) //this fake textures are not in the Update
{
for (int i = FileToMod[pos_old].NumberOfTextures - 1; i >= 0; i--) {
FileToMod[pos_old].Textures[i]->Release(); // we release the fake textures
}
//for (int i=0; i<FileToMod[pos_old].NumberOfTextures; i++) FileToMod[pos_old].Textures[i]->Release(); // we release the fake textures
delete [] FileToMod[pos_old].Textures; // we delete the memory
FileToMod[pos_old].Textures = nullptr;
pos_old++;
}
while (pos_new < NumberOfUpdate) //this fake textures are newly added
{
to_lookup[num_to_lookup++] = pos_new++; //keep this fake texture in mind, we must search later for it through all original textures
}
/*
* if (num_to_lookup>0) we need to look through all original textures
* because there were newly added textures and we don't know
* if the corresponding target textures are loaded by the game or not.
*
* Note: to_lookup[num_to_lookup++] = pos_new++; is in ascending order,
* thus Update[to_lookup[pos]].Hash is also sorted ascending!
*/
/*
uMod_IDirect3DTexture9 *single_texture = ((uMod_IDirect3DDevice9*)D3D9Device)->GetSingleTexture();
if (num_to_lookup>0)
{
int num = OriginalTextures.GetNumber();
for (int i=0; i<num; i++)
if (OriginalTextures[i]->CrossRef_D3Dtex==NULL || OriginalTextures[i]->CrossRef_D3Dtex==single_texture)
// We need look only for textures, that are not switched or switched with the single_texture.
// The single_texture is a special texture, which you can toggle through all original texture, if save single texture is turned on.
{
MyTypeHash hash = OriginalTextures[i]->Hash;
if (hash<Update[to_lookup[0]].Hash || hash>Update[to_lookup[num_to_lookup-1]].Hash) continue;
int index = -1;
int pos = num_to_lookup/2;
int begin = 0;
int end = num_to_lookup-1;
// We look in the middle of the interval and each step we halve the interval,
// unless we find the texture or the size of the interval is less than 3.
// Note: contradicting to normal C-code here the interval includes the index "begin" and "end"!
while (begin+1<end) // as long as the interval is longer than two
{
if (hash > Update[to_lookup[pos]].Hash) // the new interval is the right half of the actual interval
{
begin = pos+1; // the new interval does not contain the index "pos"
pos = (begin + end)/2; // set "pos" somewhere inside the new intervall
}
else if (hash < Update[to_lookup[pos]].Hash) // the new interval is the left half of the actual interval
{
end = pos-1; // the new interval does not contain the index "pos"
pos = (begin + end)/2; // set "pos" somewhere inside the new intervall
}
else {index = to_lookup[pos]; break;} // we hit the correct hash
}
if (index<0) // if we did not find the hash, it might be in the last interval
{
for (int i=begin; i<=end; i++) if (Update[to_lookup[i]].Hash==hash) index = to_lookup[i];
}
if (index>=0) // target texture is loaded by the game
{
if (OriginalTextures[i]->CrossRef_D3Dtex!=NULL) UnswitchTextures(OriginalTextures[i]); // this texture was switched with the single texture
uMod_IDirect3DTexture9 *fake_Texture;
if (int ret = LoadTexture( & (Update[index]), &fake_Texture)) return ret;
if (SwitchTextures( fake_Texture, OriginalTextures[i]))
{
Message("uMod_TextureClient::LookUpToMod(): textures not switched %#lX\n", FileToMod[index].Hash);
fake_Texture->Release();
}
else
{
IDirect3DBaseTexture9 **temp = new IDirect3DBaseTexture9*[Update[index].NumberOfTextures+1];
for (int j=0; j<Update[index].NumberOfTextures; j++) temp[j] = Update[index].Textures[j];
if (Update[index].Textures!=NULL) delete [] Update[index].Textures;
Update[index].Textures = temp;
Update[index].Textures[Update[index].NumberOfTextures++] = fake_Texture;
fake_Texture->Reference = index;
}
}
}
}
*/
//for (int i=0; i<NumberToMod; i++) if (FileToMod[i].Textures!=NULL) delete [] FileToMod[i].Textures;
delete [] FileToMod;
FileToMod = Update;
NumberToMod = NumberOfUpdate;
NumberOfUpdate = -1;
Update = nullptr;
if (num_to_lookup > 0) {
uMod_IDirect3DTexture9* single_texture;
void* cpy;
const long ret = D3D9Device->QueryInterface(IID_IDirect3DTexture9, &cpy);
if (ret == 0x01000000L) {
single_texture = static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->GetSingleTexture(); //this texture must no be added twice
}
else {
single_texture = static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->GetSingleTexture(); //this texture must no be added twice
}
int num = OriginalTextures.GetNumber();
for (int i = 0; i < num; i++) {
if (OriginalTextures[i]->CrossRef_D3Dtex == nullptr || OriginalTextures[i]->CrossRef_D3Dtex == single_texture) {
UnswitchTextures(OriginalTextures[i]); //this we can do always, so we unswitch the single texture
LookUpToMod(OriginalTextures[i], num_to_lookup, to_lookup);
}
}
uMod_IDirect3DVolumeTexture9* single_volume_texture;
if (ret == 0x01000000L) {
single_volume_texture = static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->GetSingleVolumeTexture(); //this texture must no be added twice
}
else {
single_volume_texture = static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->GetSingleVolumeTexture(); //this texture must no be added twice
}
num = OriginalVolumeTextures.GetNumber();
for (int i = 0; i < num; i++) {
if (OriginalVolumeTextures[i]->CrossRef_D3Dtex == nullptr || OriginalVolumeTextures[i]->CrossRef_D3Dtex == single_volume_texture) {
UnswitchTextures(OriginalVolumeTextures[i]); //this we can do always, so we unswitch the single texture
LookUpToMod(OriginalVolumeTextures[i], num_to_lookup, to_lookup);
}
}
uMod_IDirect3DCubeTexture9* single_cube_texture;
if (ret == 0x01000000L) {
single_cube_texture = static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->GetSingleCubeTexture(); //this texture must no be added twice
}
else {
single_cube_texture = static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->GetSingleCubeTexture(); //this texture must no be added twice
}
num = OriginalCubeTextures.GetNumber();
for (int i = 0; i < num; i++) {
if (OriginalCubeTextures[i]->CrossRef_D3Dtex == nullptr || OriginalCubeTextures[i]->CrossRef_D3Dtex == single_cube_texture) {
UnswitchTextures(OriginalCubeTextures[i]); //this we can do always, so we unswitch the single texture
LookUpToMod(OriginalCubeTextures[i], num_to_lookup, to_lookup);
}
}
}
delete [] to_lookup;
return UnlockMutex();
}
int uMod_TextureClient::LockMutex()
{
if ((gl_ErrorState & (uMod_ERROR_FATAL | uMod_ERROR_MUTEX))) {
return RETURN_NO_MUTEX;
}
if (WAIT_OBJECT_0 != WaitForSingleObject(Mutex, 100)) {
return RETURN_MUTEX_LOCK; //waiting 100ms, to wait infinite pass INFINITE
}
return RETURN_OK;
}
int uMod_TextureClient::UnlockMutex()
{
if (ReleaseMutex(Mutex) == 0) {
return RETURN_MUTEX_UNLOCK;
}
return RETURN_OK;
}
int uMod_TextureClient::LookUpToMod(MyTypeHash hash, int num_index_list, int* index_list)
{
if (NumberToMod > 0) {
if (index_list == nullptr || num_index_list == 0) {
if (hash < FileToMod[0].Hash || hash > FileToMod[NumberToMod - 1].Hash) {
return -1;
}
int pos = NumberToMod / 2;
int begin = 0;
int end = NumberToMod - 1;
// We look in the middle of the interval and each step we halve the interval,
// unless we find the texture or the size of the interval is less than 3.
// Note: contradicting to normal C-code here the interval includes the index "begin" and "end"!
while (begin + 1 < end) // as long as the interval is longer than two
{
if (hash > FileToMod[pos].Hash) // the new interval is the right half of the actual interval
{
begin = pos + 1; // the new interval does not contain the index "pos"
pos = (begin + end) / 2; // set "pos" somewhere inside the new interval
}
else if (hash < FileToMod[pos].Hash) // the new interval is the left half of the actual interval
{
end = pos - 1; // the new interval does not contain the index "pos"
pos = (begin + end) / 2; // set "pos" somewhere inside the new interval
}
else {
return pos;
break;
} // we hit the correct hash
}
for (pos = begin; pos <= end; pos++) {
if (FileToMod[pos].Hash == hash) {
return pos;
}
}
}
else {
if (hash < FileToMod[index_list[0]].Hash || hash > FileToMod[index_list[num_index_list - 1]].Hash) {
return -1;
}
int pos = num_index_list / 2;
int begin = 0;
int end = num_index_list - 1;
// We look in the middle of the interval and each step we halve the interval,
// unless we find the texture or the size of the interval is less than 3.
// Note: contradicting to normal C-code here the interval includes the index "begin" and "end"!
while (begin + 1 < end) // as long as the interval is longer than two
{
if (hash > FileToMod[index_list[pos]].Hash) // the new interval is the right half of the actual interval
{
begin = pos + 1; // the new interval does not contain the index "pos"
pos = (begin + end) / 2; // set "pos" somewhere inside the new interval
}
else if (hash < FileToMod[index_list[pos]].Hash) // the new interval is the left half of the actual interval
{
end = pos - 1; // the new interval does not contain the index "pos"
pos = (begin + end) / 2; // set "pos" somewhere inside the new interval
}
else {
return index_list[pos];
break;
} // we hit the correct hash
}
for (pos = begin; pos <= end; pos++) {
if (FileToMod[index_list[pos]].Hash == hash) {
return index_list[pos];
}
}
}
}
return -1;
}
int uMod_TextureClient::LookUpToMod(uMod_IDirect3DTexture9* pTexture, int num_index_list, int* index_list) // should only be called for original textures
{
Message("uMod_TextureClient::LookUpToMod( %p): hash: %#lX, %p\n", pTexture, pTexture->Hash, this);
if (pTexture->CrossRef_D3Dtex != nullptr) {
return RETURN_OK; // bug, this texture is already switched
}
const int index = LookUpToMod(pTexture->Hash, num_index_list, index_list);
if (index >= 0) {
uMod_IDirect3DTexture9* fake_Texture;
if (const int ret = LoadTexture(&(FileToMod[index]), &fake_Texture)) {
return ret;
}
if (SwitchTextures(fake_Texture, pTexture)) {
Message("uMod_TextureClient::LookUpToMod(): textures not switched %#lX\n", FileToMod[index].Hash);
fake_Texture->Release();
}
else {
const auto temp = new IDirect3DBaseTexture9*[FileToMod[index].NumberOfTextures + 1];
for (int j = 0; j < FileToMod[index].NumberOfTextures; j++) {
temp[j] = FileToMod[index].Textures[j];
}
delete [] FileToMod[index].Textures;
FileToMod[index].Textures = temp;
FileToMod[index].Textures[FileToMod[index].NumberOfTextures++] = fake_Texture;
fake_Texture->Reference = index;
}
}
return RETURN_OK;
}
int uMod_TextureClient::LookUpToMod(uMod_IDirect3DVolumeTexture9* pTexture, int num_index_list, int* index_list) // should only be called for original textures
{
Message("uMod_TextureClient::LookUpToMod( Volume %p): hash: %#lX, %p\n", pTexture, pTexture->Hash, this);
if (pTexture->CrossRef_D3Dtex != nullptr) {
return RETURN_OK; // bug, this texture is already switched
}
const int index = LookUpToMod(pTexture->Hash, num_index_list, index_list);
if (index >= 0) {
uMod_IDirect3DVolumeTexture9* fake_Texture;
if (const int ret = LoadTexture(&(FileToMod[index]), &fake_Texture)) {
return ret;
}
if (SwitchTextures(fake_Texture, pTexture)) {
Message("uMod_TextureClient::LookUpToMod(): textures not switched %#lX\n", FileToMod[index].Hash);
fake_Texture->Release();
}
else {
const auto temp = new IDirect3DBaseTexture9*[FileToMod[index].NumberOfTextures + 1];
for (int j = 0; j < FileToMod[index].NumberOfTextures; j++) {
temp[j] = FileToMod[index].Textures[j];
}
delete [] FileToMod[index].Textures;
FileToMod[index].Textures = temp;
FileToMod[index].Textures[FileToMod[index].NumberOfTextures++] = fake_Texture;
fake_Texture->Reference = index;
}
}
return RETURN_OK;
}
int uMod_TextureClient::LookUpToMod(uMod_IDirect3DCubeTexture9* pTexture, int num_index_list, int* index_list) // should only be called for original textures
{
Message("uMod_TextureClient::LookUpToMod( Cube %p): hash: %#lX, %p\n", pTexture, pTexture->Hash, this);
if (pTexture->CrossRef_D3Dtex != nullptr) {
return RETURN_OK; // bug, this texture is already switched
}
const int index = LookUpToMod(pTexture->Hash, num_index_list, index_list);
if (index >= 0) {
uMod_IDirect3DCubeTexture9* fake_Texture;
if (const int ret = LoadTexture(&(FileToMod[index]), &fake_Texture)) {
return ret;
}
if (SwitchTextures(fake_Texture, pTexture)) {
Message("uMod_TextureClient::LookUpToMod(): textures not switched %#lX\n", FileToMod[index].Hash);
fake_Texture->Release();
}
else {
const auto temp = new IDirect3DBaseTexture9*[FileToMod[index].NumberOfTextures + 1];
for (int j = 0; j < FileToMod[index].NumberOfTextures; j++) {
temp[j] = FileToMod[index].Textures[j];
}
delete [] FileToMod[index].Textures;
FileToMod[index].Textures = temp;
FileToMod[index].Textures[FileToMod[index].NumberOfTextures++] = fake_Texture;
fake_Texture->Reference = index;
}
}
return RETURN_OK;
}
int uMod_TextureClient::LoadTexture(TextureFileStruct* file_in_memory, uMod_IDirect3DTexture9** ppTexture) // to load fake texture from a file in memory
{
Message("LoadTexture( %p, %p, %#lX): %p\n", file_in_memory, ppTexture, file_in_memory->Hash, this);
if (D3D_OK != D3DXCreateTextureFromFileInMemoryEx(D3D9Device, file_in_memory->pData, file_in_memory->Size, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, nullptr, nullptr,
(IDirect3DTexture9**)ppTexture))
//if (D3D_OK != D3DXCreateTextureFromFileInMemory( D3D9Device, file_in_memory->pData, file_in_memory->Size, (IDirect3DTexture9 **) ppTexture))
{
*ppTexture = nullptr;
return RETURN_TEXTURE_NOT_LOADED;
}
(*ppTexture)->FAKE = true;
void* cpy;
const long ret = D3D9Device->QueryInterface(IID_IDirect3DTexture9, &cpy);
if (ret == 0x01000000L) {
static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->SetLastCreatedTexture(nullptr); //this texture must no be added twice
}
else {
static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->SetLastCreatedTexture(nullptr); //this texture must no be added twice
}
Message("LoadTexture( %p, %#lX): DONE\n", *ppTexture, file_in_memory->Hash);
return RETURN_OK;
}
int uMod_TextureClient::LoadTexture(TextureFileStruct* file_in_memory, uMod_IDirect3DVolumeTexture9** ppTexture) // to load fake texture from a file in memory
{
Message("LoadTexture( Volume %p, %p, %#lX): %p\n", file_in_memory, ppTexture, file_in_memory->Hash, this);
if (D3D_OK != D3DXCreateVolumeTextureFromFileInMemoryEx(D3D9Device, file_in_memory->pData, file_in_memory->Size, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, nullptr,
nullptr,
(IDirect3DVolumeTexture9**)ppTexture))
//if (D3D_OK != D3DXCreateVolumeTextureFromFileInMemory( D3D9Device, file_in_memory->pData, file_in_memory->Size, (IDirect3DVolumeTexture9 **) ppTexture))
{
*ppTexture = nullptr;
return RETURN_TEXTURE_NOT_LOADED;
}
(*ppTexture)->FAKE = true;
void* cpy;
const long ret = D3D9Device->QueryInterface(IID_IDirect3DTexture9, &cpy);
if (ret == 0x01000000L) {
static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->SetLastCreatedVolumeTexture(nullptr); //this texture must no be added twice
}
else {
static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->SetLastCreatedVolumeTexture(nullptr); //this texture must no be added twice
}
Message("LoadTexture( Volume %p, %#lX): DONE\n", *ppTexture, file_in_memory->Hash);
return RETURN_OK;
}
int uMod_TextureClient::LoadTexture(TextureFileStruct* file_in_memory, uMod_IDirect3DCubeTexture9** ppTexture) // to load fake texture from a file in memory
{
Message("LoadTexture( Cube %p, %p, %#lX): %p\n", file_in_memory, ppTexture, file_in_memory->Hash, this);
if (D3D_OK != D3DXCreateCubeTextureFromFileInMemoryEx(D3D9Device, file_in_memory->pData, file_in_memory->Size, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, nullptr, nullptr,
(IDirect3DCubeTexture9**)ppTexture))
//if (D3D_OK != D3DXCreateCubeTextureFromFileInMemory( D3D9Device, file_in_memory->pData, file_in_memory->Size, (IDirect3DCubeTexture9 **) ppTexture))
{
*ppTexture = nullptr;
return RETURN_TEXTURE_NOT_LOADED;
}
(*ppTexture)->FAKE = true;
void* cpy;
const long ret = D3D9Device->QueryInterface(IID_IDirect3DTexture9, &cpy);
if (ret == 0x01000000L) {
static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->SetLastCreatedCubeTexture(nullptr); //this texture must no be added twice
}
else {
static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->SetLastCreatedCubeTexture(nullptr); //this texture must no be added twice
}
Message("LoadTexture( Cube %p, %#lX): DONE\n", *ppTexture, file_in_memory->Hash);
return RETURN_OK;
}
-40
View File
@@ -1,40 +0,0 @@
#include "uMod_Main.h"
/*
MyTypeHash GetHash(unsigned char *str, int len) // estimate the hash
{
MyTypeHash hash = 0;
for (int i=0; i<len; i++) hash = str[i] + (hash << 6) + (hash << 16) - hash;
return hash);
}
*/
/*
*
* BIG THANKS TO RS !!
*
* who gave me his hashing algorithm (well or crc32 algorithm^^)
*
The hash function is CRC32 using polynomial 0xEDB88320.
However, the hashed data is calculated incorrectly in TexMod: it's simply BytesPerPixel * Width * Height, from the beginning of the data (that is mapped using LockRect).
The problem is that it doesn't take the pitch into account and BytesPerPixel may be wrong for some rare formats (not sure about that).
*/
#define CRC32POLY 0xEDB88320u /* CRC-32 Polynom */
#define ulCrc_in 0xffffffff
unsigned int GetCRC32(char* pcDatabuf, unsigned int ulDatalen)
{
unsigned int crc = ulCrc_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 ? CRC32POLY : 0);
}
}
return crc;
}
-271
View File
@@ -1,271 +0,0 @@
#include <algorithm>
#include <filesystem>
#include <fstream>
#include "uMod_Main.h"
#include "gMod_FileLoader.h"
unsigned long loadedSize = 0;
uMod_TextureServer::uMod_TextureServer(char* game, char* uModName)
{
Message("uMod_TextureServer(): %p\n", this);
Client = nullptr;
int len = 0;
int path_pos = 0;
int dot_pos = 0;
for (len = 0; len < MAX_PATH && (game[len]); len++) {
if (game[len] == '\\' || game[len] == '/') {
path_pos = len + 1;
}
else if (game[len] == '.') {
dot_pos = len;
}
}
if (dot_pos > path_pos) {
len = dot_pos - path_pos;
}
else {
len -= path_pos;
}
for (int i = 0; i < len; i++) {
GameName[i] = game[i + path_pos];
}
if (len < MAX_PATH) {
GameName[len] = 0;
}
else {
GameName[0] = 0;
}
strcpy(UModName, uModName);
}
uMod_TextureServer::~uMod_TextureServer()
{
Message("~uMod_TextureServer(): %p\n", this);
//delete the files in memory
int num = CurrentMod.GetNumber();
for (int i = 0; i < num; i++) {
delete[] CurrentMod[i]->pData; //delete the file content of the texture
}
num = OldMod.GetNumber();
for (int i = 0; i < num; i++) {
delete[] OldMod[i]->pData; //delete the file content of the texture
}
}
int uMod_TextureServer::AddClient(uMod_TextureClient* client, TextureFileStruct** update, int* number) // called from a client
{
Message("AddClient(%p): %p\n", client, this);
// the following functions must not change the original uMod_IDirect3DDevice9 object
// somehow on game start some uMod_IDirect3DDevice9 object are created, which must rest unchanged!!
// these objects are released and are not used for rendering
if (const int ret = PrepareUpdate(update, number)) {
return ret; // get a copy of all texture to be modded
}
Client = client;
return RETURN_OK;
}
int uMod_TextureServer::AddFile(char* dataPtr, unsigned int size, MyTypeHash hash, bool force) // called from Mainloop()
{
Message("uMod_TextureServer::AddFile( %p %p, %#lX, %d): %p\n", dataPtr, size, hash, force, this);
TextureFileStruct* temp = nullptr;
int num = CurrentMod.GetNumber();
for (int i = 0; i < num; i++) {
if (CurrentMod[i]->Hash == hash) //look through all current textures
{
if (force) {
temp = CurrentMod[i];
break;
} // we need to reload it
return RETURN_EXISTS; // we still have added this texture
}
}
if (temp == nullptr) // if not found, look through all old textures
{
num = OldMod.GetNumber();
for (int i = 0; i < num; i++) {
if (OldMod[i]->Hash == hash) {
temp = OldMod[i];
OldMod.Remove(temp);
CurrentMod.Add(temp);
if (force) {
break; // we must reload it
}
return RETURN_EXISTS; // we should not reload it
}
}
}
bool new_file = true;
if (temp != nullptr) //if it was found, we delete the old file content
{
new_file = false;
delete[] temp->pData; // todo: this tries deleting memory out of a vector of tpfentries, which won't do anything
// todo: therefore we don't get out memory back here
temp->pData = nullptr;
}
else //if it was not found, we need to create a new object
{
new_file = true;
temp = new TextureFileStruct;
temp->Reference = -1;
}
temp->pData = dataPtr;
temp->Size = size;
temp->NumberOfTextures = 0;
temp->Textures = nullptr;
temp->Hash = hash;
//if (new_file) temp->ForceReload = false; // no need to force a load of the texture
//else
temp->ForceReload = force;
Message("End AddFile(%#lX)\n", hash);
if (new_file) {
return CurrentMod.Add(temp); // new files must be added to the list of the CurrentMod
}
return RETURN_OK;
}
int uMod_TextureServer::PropagateUpdate(uMod_TextureClient* client) // called from Mainloop(), send the update to all clients
{
Message("PropagateUpdate(%p): %p\n", client, this);
if (client != nullptr) {
TextureFileStruct* update;
int number;
if (const int ret = PrepareUpdate(&update, &number)) {
return ret;
}
client->AddUpdate(update, number);
}
return RETURN_OK;
}
void cpy_file_struct(TextureFileStruct& a,TextureFileStruct& b)
{
a.ForceReload = b.ForceReload;
a.pData = b.pData;
a.Size = b.Size;
a.NumberOfTextures = b.NumberOfTextures;
a.Reference = b.Reference;
a.Textures = b.Textures;
a.Hash = b.Hash;
}
int TextureFileStruct_Compare(const void* elem1, const void* elem2)
{
const auto tex1 = (TextureFileStruct*)elem1;
const auto tex2 = (TextureFileStruct*)elem2;
if (tex1->Hash < tex2->Hash) {
return -1;
}
if (tex1->Hash > tex2->Hash) {
return +1;
}
return 0;
}
int uMod_TextureServer::PrepareUpdate(TextureFileStruct** update, int* number) // called from the PropagateUpdate() and AddClient.
// Prepare an update for one client. The allocated memory must deleted by the client.
{
Message("PrepareUpdate(%p, %d): %p\n", update, number, this);
TextureFileStruct* temp = nullptr;
const int num = CurrentMod.GetNumber();
if (num > 0) {
try { temp = new TextureFileStruct[num]; }
catch (...) {
gl_ErrorState |= uMod_ERROR_MEMORY | uMod_ERROR_SERVER;
return RETURN_NO_MEMORY;
}
for (int i = 0; i < num; i++) cpy_file_struct(temp[i], *CurrentMod[i]);
qsort(temp, num, sizeof(TextureFileStruct), TextureFileStruct_Compare);
}
*update = temp;
*number = num;
return RETURN_OK;
}
void uMod_TextureServer::LoadModsFromFile(const char* source)
{
Message("Initialize: searching in %s\n", source);
std::ifstream file(source);
if (file.is_open()) {
Message("Initialize: found modlist.txt. Reading\n");
std::string line;
while (std::getline(file, line)) {
Message("Initialize: loading file %s\n", line.c_str());
// Remove newline character
line.erase(std::ranges::remove(line, '\n').begin(), line.end());
auto file_loader = gMod_FileLoader(line);
const auto entries = file_loader.GetContents();
if (loadedSize > 1'500'000'000) {
Message("LoadModsFromFile: Loaded %d bytes, aborting!!!", loadedSize);
return;
}
if (!entries.empty()) {
Message("Initialize: Texture count %zu %s\n", entries.size(), line.c_str());
for (const auto& tpf_entry : entries) {
loadedSize += tpf_entry.size;
if (AddFile(static_cast<char*>(tpf_entry.data), static_cast<unsigned int>(tpf_entry.size), tpf_entry.crc_hash, false) == RETURN_EXISTS) {
//Texture is already loaded, so we need to clear our data
loadedSize -= tpf_entry.size;
}
Message("LoadModsFromFile: Loaded %d bytes", loadedSize);
}
PropagateUpdate(Client);
}
else {
Message("Initialize: Failed to load any textures for %s\n", line.c_str());
}
}
Message("Finished loading mods: Loaded %u bytes (%u mb)", loadedSize, loadedSize / 1024 / 1024);
}
}
int uMod_TextureServer::Initialize()
{
Message("Initialize: begin\n");
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
const auto exe = std::filesystem::path(gwpath).parent_path();
const auto dll = std::filesystem::path(UModName).parent_path();
for (const auto& path : {exe, dll}) {
const auto modlist = path / "modlist.txt";
if (std::filesystem::exists(modlist)) {
LoadModsFromFile(modlist.string().c_str());
}
}
Message("Initialize: end\n");
return RETURN_OK;
}