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:
@@ -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