mirror of
https://github.com/gwdevhub/gMod.git
synced 2026-07-15 15:09:30 +00:00
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:
+14
@@ -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
@@ -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>"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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/")
|
||||
@@ -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
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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,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,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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <Windows.h>
|
||||
|
||||
struct UModTexture {
|
||||
std::vector<char> data;
|
||||
std::string name;
|
||||
DWORD64 hash;
|
||||
};
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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");
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
#include "uMod_Main.h"
|
||||
#include "Main.h"
|
||||
|
||||
#define uMod_IDirect3DDevice9 uMod_IDirect3DDevice9Ex
|
||||
#define IDirect3DDevice9 IDirect3DDevice9Ex
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user