rename to gmod, drop gui (#1)

* remove GUI parts as those will not be updated

* move to header/source

* add cmakelist to create solution

* Change Readme

* Implement modlist.txt loading

* Setup versioning and CD pipeline

* Setup DirectX in pipeline

* Make uMod load from uMod.dll directory

* Fix file loading

* Remove break

* Fix CD pipeline (#1)

* Test cd pipeline

* See what's in Lib directory

* See inside lib/x86

* Manually adjust the build environment

* Disable CD pipeline in PRs
Create CI pipeline

* Fix slashes in path

* Fix build call

* Attempt to fix paths

* Copy dx headers inside the /header folder

* Use ps

* Change cache location

* Path changes

* Improve CMake to look for lib and header files

* Fix missing Lib folder

* Move changes to CD pipeline

* Disable CI on merge and fix CD (#2)

* Fix CD tag (#4)

* Hijack existing DirectX calls (#5)

* Create a dll without listener (#6)

* Fix asset creation in CD pipeline (#7)

* Setup file loading

* create necessary files

* merge latest changes, set output dir

* Change main to master in pipelines
Add fallback for DX libs in CMakeLists

* Setup new generator

* formatting

* remove listener

* Change CD to pick the dll from bin
Change release name to gMod

* more formatting

* add editorconfig

* Setup versioning

* Remove CODEOWNERS

---------

Co-authored-by: Alex Macocian <amacocian@yahoo.com>
This commit is contained in:
DubbleClick
2023-11-10 17:40:30 +01:00
committed by GitHub
parent 929756bca3
commit a7e36fc965
120 changed files with 15004 additions and 21714 deletions
+99
View File
@@ -0,0 +1,99 @@
#include "uMod_Main.h"
uMod_FileHandler::uMod_FileHandler()
{
Message("uMod_FileHandler(): %lu\n", this);
Number = 0;
FieldCounter = 0;
Files = nullptr;
}
uMod_FileHandler::~uMod_FileHandler()
{
Message("~uMod_FileHandler(): %lu\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(%lu): %lu\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(%lu): %lu\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;
}
+365
View File
@@ -0,0 +1,365 @@
#include "uMod_DX9_dll.h"
#include "uMod_Main.h"
#include <Windows.h>
#include <Psapi.h>
#include <TlHelp32.h>
#pragma comment(lib, "Psapi.lib")
//#include "detours.h"
//#include "detourxs/detourxs/detourxs.h"
/*
#include "detourxs/detourxs/ADE32.cpp"
#include "detourxs/detourxs/detourxs.cpp"
*/
/*
* global variable which are not linked external
*/
HINSTANCE gl_hOriginalDll = nullptr;
HINSTANCE gl_hThisInstance = nullptr;
uMod_TextureServer* gl_TextureServer = nullptr;
HANDLE gl_ServerThread = 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 BUILD_TYPE_DEBUG
AllocConsole();
SetConsoleTitleA("uMod 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;
}
DWORD WINAPI ServerThread(LPVOID lpParam)
{
UNREFERENCED_PARAMETER(lpParam);
if (gl_TextureServer != nullptr) {
gl_TextureServer->MainLoop(); //This is and endless mainloop, it sleep till something is written into the pipe.
}
return 0;
}
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: %lu\n", hModule);
char uMod[MAX_PATH];
for (auto i = 0; i < MAX_PATH; i++) {
uMod[i] = 0;
}
GetModuleFileNameA(hModule, uMod, MAX_PATH);
Message("InitInstance: %s\n", uMod);
gl_TextureServer = new uMod_TextureServer(game, uMod); //create the server which listen on the pipe and prepare the update for the texture clients
LoadOriginalDll();
if (gl_hOriginalDll) {
Direct3DCreate9_fn = (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 = (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_ServerThread = CreateThread(nullptr, 0, ServerThread, nullptr, 0, nullptr); //creating a thread for the mainloop
if (gl_ServerThread == nullptr) { Message("InitInstance: Serverthread not started\n"); }
}
}
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()
{
if (gl_ServerThread != nullptr) {
CloseHandle(gl_ServerThread); // kill the server thread
gl_ServerThread = nullptr;
}
if (gl_TextureServer != nullptr) {
delete gl_TextureServer; //delete the texture server
gl_TextureServer = nullptr;
}
// Release the system's d3d9.dll
if (gl_hOriginalDll != nullptr) {
FreeLibrary(gl_hOriginalDll);
gl_hOriginalDll = nullptr;
}
#ifdef BUILD_TYPE_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 %lu, uMod %lu\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); //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 %lu, uMod %lu\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); //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
int i = 0;
while (Game[i]) {
ret[i] = Game[i];
i++;
}
ret[i] = 0;
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;
}
+485
View File
@@ -0,0 +1,485 @@
#include "uMod_Main.h"
#include "unzip.h"
#include "uMod_File.h"
#include "utils.h"
#include "uMod_Texture.h"
#include <fstream>
#include <sstream>
#include <vector>
#ifdef __CDT_PARSER__
#define FindZipItem(...) 0
#define UnzipItem(...) 0
#define CloseZip(...) 0
#define GetZipItem(...) 0
#endif
uMod_File::uMod_File()
{
Loaded = false;
XORed = false;
FileInMemory = static_cast<char*>(nullptr);
MemoryLength = 0u;
FileLen = 0u;
}
uMod_File::uMod_File(const std::string file)
{
Loaded = false;
XORed = false;
FileInMemory = static_cast<char*>(nullptr);
MemoryLength = 0u;
FileLen = 0u;
SetFile(file);
}
uMod_File::~uMod_File()
{
if (FileInMemory != static_cast<char*>(nullptr)) {
delete[] FileInMemory;
}
}
bool uMod_File::FileSupported()
{
const std::string file_type = GetFileExtension(FileName);
if (file_type == "zip") {
return true;
}
if (file_type == "tpf") {
return true;
}
if (file_type == "bmp") {
return true;
}
if (file_type == "jpg") {
return true;
}
if (file_type == "tga") {
return true;
}
if (file_type == "png") {
return true;
}
if (file_type == "dds") {
return true;
}
if (file_type == "ppm") {
return true;
}
return false;
}
bool uMod_File::PackageFile()
{
const std::string file_type = GetFileExtension(FileName);
if (file_type == "zip") {
return true;
}
if (file_type == "tpf") {
return true;
}
return false;
}
bool uMod_File::SingleFile()
{
const std::string file_type = GetFileExtension(FileName);
if (file_type == "bmp") {
return true;
}
if (file_type == "jpg") {
return true;
}
if (file_type == "tga") {
return true;
}
if (file_type == "png") {
return true;
}
if (file_type == "dds") {
return true;
}
if (file_type == "ppm") {
return true;
}
return false;
}
int uMod_File::GetContent()
{
const std::string file_type = GetFileExtension(FileName);
if (file_type == "zip") {
AddZip();
}
else if (file_type == "tpf") {
AddTpf();
}
else if (SingleFile()) {
AddFile();
}
else {
printf(FileName.c_str());
printf(" Not supported\n");
return -1;
}
return 0;
}
int uMod_File::ReadFile()
{
if (Loaded) {
return 0;
}
XORed = false;
const auto name = FileName;
std::ifstream inputFile(name, std::ios::binary);
if (!inputFile ||
!inputFile.is_open()) {
printf(name.c_str());
printf(" Could not open\n");
return -1;
}
const std::vector<char> buffer(std::istreambuf_iterator<char>(inputFile), {});
if (FileInMemory) {
delete[] FileInMemory;
}
FileInMemory = new char[buffer.size()];
for (auto i = 0; i < buffer.size(); i++) {
FileInMemory[i] = buffer[i];
}
FileLen = buffer.size();
inputFile.close();
FileInMemory[FileLen] = 0;
printf(name.c_str());
printf("%d\n", FileLen);
Loaded = true;
return 0;
}
int uMod_File::UnXOR()
{
if (XORed) {
return 0;
}
/*
*
* BIG THANKS TO Tonttu
* (TPFcreate 1.5)
*
*/
const auto buff = (unsigned int*)FileInMemory;
const unsigned int TPF_XOR = 0x3FA43FA4u;
const unsigned int size = FileLen / 4u;
for (unsigned int i = 0; i < size; i++) {
buff[i] ^= TPF_XOR;
}
for (unsigned int i = size * 4u; i < size * 4u + FileLen % 4u; i++) {
((unsigned char*)FileInMemory)[i] ^= static_cast<unsigned char>(TPF_XOR);
}
unsigned int pos = FileLen - 1;
while (pos > 0u && FileInMemory[pos]) {
pos--;
}
if (pos > 0u && pos < FileLen - 1) {
FileLen = pos + 1;
}
XORed = true;
/*
* original code by Tonttu
* The last bytes are not revealed correctly
unsigned int j=0;
while ( j <= result - 4 )
{
*( unsigned int* )( &buffer[j] ) ^= TPF_XOR;
j += 4;
}
while ( j < result )
{
buffer[j] ^= (unsigned char )( TPF_XOR >> 24 );
TPF_XOR <<= 4;
j++;
}
*/
return 0;
}
int uMod_File::AddFile()
{
DWORD64 temp_hash;
std::string name = AfterLast(FileName, '_');
name = BeforeLast(name, '.');
try {
// Convert hexadecimal string to unsigned long long
temp_hash = std::stoull(name, nullptr, 16);
}
catch (const std::invalid_argument& e) {
printf("Encountered error");
printf(e.what());
}
catch (const std::out_of_range& e) {
printf("Encountered error");
printf(e.what());
}
if (const int ret = ReadFile()) {
return ret;
}
FileHash = temp_hash;
return 0;
}
int uMod_File::AddZip()
{
if (const int ret = ReadFile()) {
return ret;
}
return AddContent(nullptr);
}
int uMod_File::AddTpf()
{
if (const int ret = ReadFile()) {
return ret;
}
UnXOR();
constexpr char pw[] = {
0x73, 0x2A, 0x63, 0x7D, 0x5F, 0x0A, static_cast<char>(0xA6), static_cast<char>(0xBD),
0x7D, 0x65, 0x7E, 0x67, 0x61, 0x2A, 0x7F, 0x7F,
0x74, 0x61, 0x67, 0x5B, 0x60, 0x70, 0x45, 0x74,
0x5C, 0x22, 0x74, 0x5D, 0x6E, 0x6A, 0x73, 0x41,
0x77, 0x6E, 0x46, 0x47, 0x77, 0x49, 0x0C, 0x4B,
0x46, 0x6F, '\0'
};
return AddContent(pw);
}
int uMod_File::AddContent(const char* pw)
{
// Thats is really nasty code, but atm I am happy that it works. I should try an other unzip api,
// This one seems to behave very strange.
// I know, that also a bug in my code could be reason for the crashes, but UnzipItem( ... ) unzipes wrong files
// and GetZipItem( ... ) returns garbage as file names, and the next call of GetZipItem( ... ) blows up the program.
//
// I have commented line 3519 in unzip.cpp.
// It was stated this is a bug, but it did not solve my problems.
//
// closing and reopen the zip handle did the trick.
//
const auto& name = FileName;
HZIP ZIP_Handle = OpenZip(FileInMemory, FileLen, pw);
if (ZIP_Handle == static_cast<HZIP>(nullptr)) {
printf(name.c_str());
printf(" Failed to unzip file\n");
return -1;
}
ZIPENTRY ze;
int index;
FindZipItem(ZIP_Handle, "texmod.def", false, &index, &ze);
if (index >= 0) //if texmod.def is present in the zip file
{
printf(name.c_str());
printf(" Unzipping based on texmod.def of size %d\n", ze.unc_size);
char* def;
int len = ze.unc_size;
try { def = new char[len + 1]; }
catch (...) {
printf(name.c_str());
printf(" Memory error\n");
return -1;
}
ZRESULT zr = UnzipItem(ZIP_Handle, index, def, len);
if (zr != ZR_OK && zr != ZR_MORE) {
delete[] def;
return -1;
}
def[len] = 0;
std::stringstream tokenStream(def);
std::string token;
DWORD64 temp_hash;
std::string entry;
std::string file;
while (std::getline(tokenStream, token)) {
entry = token;
printf(name.c_str());
printf(" Parsing token %s\n", token.c_str());
file = BeforeFirst(token, '|');
try {
temp_hash = std::stoull(file, nullptr, 16);
// Successful conversion; can continue processing...
}
catch (const std::invalid_argument&) {
// Handle invalid argument
printf(name.c_str());
printf(" Invalid hash\n");
continue; // Skip the rest of the current loop iteration
}
catch (const std::out_of_range&) {
// Handle out of range
printf(name.c_str());
printf(" Invalid hash\n");
continue; // Skip the rest of the current loop iteration
}
file = AfterFirst(entry, '|');
ReplaceAll(file, "\r", "");
while ((!file.empty() && file[0] == '.' && (file.size() > 1 && (file[1] == '/' || file[1] == '\\')))
|| (!file.empty() && (file[0] == '/' || file[0] == '\\'))) {
file.erase(0, 1);
}
FindZipItem(ZIP_Handle, file.c_str(), false, &index, &ze); // look for texture
if (index >= 0) {
std::vector<char> data;
UModTexture texture;
data.resize(ze.unc_size);
ZRESULT rz = UnzipItem(ZIP_Handle, index, data.data(), ze.unc_size);
if (rz != ZR_OK && rz != ZR_MORE) {
printf(name.c_str());
printf(" Unzip error\n");
}
else {
texture.hash = temp_hash;
texture.data = data;
texture.name = file;
Textures.push_back(texture);
printf(name.c_str());
printf(" Added texture of size %d %s\n", data.size(), file.c_str());
}
}
else {
printf(name.c_str());
printf(" Unzip error\n");
CloseZip(ZIP_Handle); //somehow we need to close and to reopen the zip handle, otherwise the program crashes
ZIP_Handle = OpenZip(FileInMemory, FileLen, pw);
}
}
delete[] def;
CloseZip(ZIP_Handle);
if (Textures.size() == 0) {
printf(name.c_str());
printf(" No textures parsed\n");
return -1;
}
return 0;
}
//we load each dds file
{
printf(name.c_str());
printf(" Unzipping without texmode.def\n");
CloseZip(ZIP_Handle); //somehow we need to close and to reopen the zip handle, otherwise the program crashes
ZIP_Handle = OpenZip(FileInMemory, FileLen, pw);
if (ZIP_Handle == static_cast<HZIP>(nullptr)) {
printf(name.c_str());
printf(" Failed to unzip file");
return -1;
}
std::string file;
GetZipItem(ZIP_Handle, -1, &ze); //ask for number of entries
int num = ze.index;
DWORD64 temp_hash;
for (int i = 0; i < num; i++) {
if (GetZipItem(ZIP_Handle, i, &ze) != ZR_OK) {
continue; //ask for name and size
}
int len = ze.unc_size;
printf(name.c_str());
printf(" Parsing token %s\n", ze.name);
std::vector<char> data;
UModTexture texture;
data.resize(ze.unc_size);
ZRESULT rz = UnzipItem(ZIP_Handle, i, data.data(), len);
if (rz != ZR_OK && rz != ZR_MORE) {
printf(name.c_str());
printf(" Unzip error\n");
continue;
}
file = ze.name;
if (file.size() == 0) {
continue;
}
if (file == "Comment.txt") // skip comment
{
continue;
}
auto entryName = AfterLast(file, '.');
if (entryName != "dds") {
continue;
}
entryName = AfterLast(file, L'_');
entryName = BeforeLast(entryName, L'.');
try {
temp_hash = std::stoull(entryName, nullptr, 16); // Convert hex string to number
}
catch (const std::invalid_argument& e) {
printf(name.c_str());
printf(" Invalid hash\n");
continue;
}
catch (const std::out_of_range& e) {
printf(name.c_str());
printf(" Invalid hash\n");
continue;
}
texture.hash = temp_hash;
texture.name = entryName;
texture.data = data;
Textures.push_back(texture);
printf(name.c_str());
printf(" Added texture of size %d %s\n", data.size(), entryName.c_str());
}
CloseZip(ZIP_Handle);
if (Textures.size() == 0) {
printf(name.c_str());
printf(" No textures parsed\n");
return -1;
}
return 0;
}
return 0;
}
+135
View File
@@ -0,0 +1,135 @@
#include "uMod_Main.h"
#ifndef PRE_MESSAGE
#define PRE_MESSAGE "uMod_IDirect3D9"
#endif
uMod_IDirect3D9::uMod_IDirect3D9(IDirect3D9* pOriginal, uMod_TextureServer* server)
{
Message(PRE_MESSAGE "::" PRE_MESSAGE "( %lu, %lu): %lu\n", pOriginal, server, this);
m_pIDirect3D9 = pOriginal;
uMod_Server = server;
}
uMod_IDirect3D9::~uMod_IDirect3D9()
{
Message(PRE_MESSAGE "::~" PRE_MESSAGE "(): %lu\n", this);
}
HRESULT __stdcall uMod_IDirect3D9::QueryInterface(REFIID riid, void** ppvObj)
{
*ppvObj = nullptr;
// call this to increase AddRef at original object
// and to check if such an interface is there
const HRESULT hRes = m_pIDirect3D9->QueryInterface(riid, ppvObj);
if (hRes == NOERROR) // if OK, send our "fake" address
{
*ppvObj = this;
}
return hRes;
}
ULONG __stdcall uMod_IDirect3D9::AddRef()
{
return m_pIDirect3D9->AddRef();
}
ULONG __stdcall uMod_IDirect3D9::Release()
{
// call original routine
const ULONG count = m_pIDirect3D9->Release();
// in case no further Ref is there, the Original Object has deleted itself
if (count == 0) {
delete this;
}
return count;
}
HRESULT __stdcall uMod_IDirect3D9::RegisterSoftwareDevice(void* pInitializeFunction)
{
return m_pIDirect3D9->RegisterSoftwareDevice(pInitializeFunction);
}
UINT __stdcall uMod_IDirect3D9::GetAdapterCount()
{
return m_pIDirect3D9->GetAdapterCount();
}
HRESULT __stdcall uMod_IDirect3D9::GetAdapterIdentifier(UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER9* pIdentifier)
{
return m_pIDirect3D9->GetAdapterIdentifier(Adapter, Flags, pIdentifier);
}
UINT __stdcall uMod_IDirect3D9::GetAdapterModeCount(UINT Adapter, D3DFORMAT Format)
{
return m_pIDirect3D9->GetAdapterModeCount(Adapter, Format);
}
HRESULT __stdcall uMod_IDirect3D9::EnumAdapterModes(UINT Adapter, D3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode)
{
return m_pIDirect3D9->EnumAdapterModes(Adapter, Format, Mode, pMode);
}
HRESULT __stdcall uMod_IDirect3D9::GetAdapterDisplayMode(UINT Adapter, D3DDISPLAYMODE* pMode)
{
return m_pIDirect3D9->GetAdapterDisplayMode(Adapter, pMode);
}
HRESULT __stdcall uMod_IDirect3D9::CheckDeviceType(UINT iAdapter, D3DDEVTYPE DevType, D3DFORMAT DisplayFormat, D3DFORMAT BackBufferFormat, BOOL bWindowed)
{
return m_pIDirect3D9->CheckDeviceType(iAdapter, DevType, DisplayFormat, BackBufferFormat, bWindowed);
}
HRESULT __stdcall uMod_IDirect3D9::CheckDeviceFormat(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat)
{
return m_pIDirect3D9->CheckDeviceFormat(Adapter, DeviceType, AdapterFormat, Usage, RType, CheckFormat);
}
HRESULT __stdcall uMod_IDirect3D9::CheckDeviceMultiSampleType(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels)
{
return m_pIDirect3D9->CheckDeviceMultiSampleType(Adapter, DeviceType, SurfaceFormat, Windowed, MultiSampleType, pQualityLevels);
}
HRESULT __stdcall uMod_IDirect3D9::CheckDepthStencilMatch(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat)
{
return m_pIDirect3D9->CheckDepthStencilMatch(Adapter, DeviceType, AdapterFormat, RenderTargetFormat, DepthStencilFormat);
}
HRESULT __stdcall uMod_IDirect3D9::CheckDeviceFormatConversion(UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SourceFormat, D3DFORMAT TargetFormat)
{
return m_pIDirect3D9->CheckDeviceFormatConversion(Adapter, DeviceType, SourceFormat, TargetFormat);
}
HRESULT __stdcall uMod_IDirect3D9::GetDeviceCaps(UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9* pCaps)
{
return m_pIDirect3D9->GetDeviceCaps(Adapter, DeviceType, pCaps);
}
HMONITOR __stdcall uMod_IDirect3D9::GetAdapterMonitor(UINT Adapter)
{
return m_pIDirect3D9->GetAdapterMonitor(Adapter);
}
HRESULT __stdcall uMod_IDirect3D9::CreateDevice(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface)
{
Message(PRE_MESSAGE "::CreateDevice(): %lu\n", this);
// we intercept this call and provide our own "fake" Device Object
const HRESULT hres = m_pIDirect3D9->CreateDevice(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
int count = 1;
if (pPresentationParameters != nullptr) {
count = pPresentationParameters->BackBufferCount;
}
const auto pIDirect3DDevice9 = new uMod_IDirect3DDevice9(*ppReturnedDeviceInterface, uMod_Server, count);
// store our pointer (the fake one) for returning it to the calling program
*ppReturnedDeviceInterface = pIDirect3DDevice9;
return hres;
}
+48
View File
@@ -0,0 +1,48 @@
#include "uMod_Main.h"
#define IDirect3D9 IDirect3D9Ex
#define uMod_IDirect3D9 uMod_IDirect3D9Ex
#define m_pIDirect3D9 m_pIDirect3D9Ex
#define PRE_MESSAGE "uMod_IDirect3D9Ex"
// ReSharper disable once CppUnusedIncludeDirective
#include "uMod_IDirect3D9.cpp"
HRESULT __stdcall uMod_IDirect3D9Ex::CreateDeviceEx(UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode,
IDirect3DDevice9Ex** ppReturnedDeviceInterface)
{
Message("uMod_IDirect3D9Ex::CreateDeviceEx: %lu\n", this);
// we intercept this call and provide our own "fake" Device Object
const HRESULT hres = m_pIDirect3D9Ex->CreateDeviceEx(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, pFullscreenDisplayMode, ppReturnedDeviceInterface);
int count = 1;
if (pPresentationParameters != nullptr) {
count = pPresentationParameters->BackBufferCount;
}
const auto pIDirect3DDevice9Ex = new uMod_IDirect3DDevice9Ex(*ppReturnedDeviceInterface, uMod_Server, count);
// store our pointer (the fake one) for returning it to the calling program
*ppReturnedDeviceInterface = pIDirect3DDevice9Ex;
return hres;
}
HRESULT __stdcall uMod_IDirect3D9Ex::EnumAdapterModesEx(UINT Adapter, const D3DDISPLAYMODEFILTER* pFilter, UINT Mode, D3DDISPLAYMODEEX* pMode)
{
return m_pIDirect3D9Ex->EnumAdapterModesEx(Adapter, pFilter, Mode, pMode);
}
HRESULT __stdcall uMod_IDirect3D9Ex::GetAdapterDisplayModeEx(UINT Adapter, D3DDISPLAYMODEEX* pMode, D3DDISPLAYROTATION* pRotation)
{
return m_pIDirect3D9Ex->GetAdapterDisplayModeEx(Adapter, pMode, pRotation);
}
HRESULT __stdcall uMod_IDirect3D9Ex::GetAdapterLUID(UINT Adapter, LUID* pLUID)
{
return m_pIDirect3D9Ex->GetAdapterLUID(Adapter, pLUID);
}
UINT __stdcall uMod_IDirect3D9Ex::GetAdapterModeCountEx(UINT Adapter, const D3DDISPLAYMODEFILTER* pFilter)
{
return m_pIDirect3D9Ex->GetAdapterModeCountEx(Adapter, pFilter);
}
+360
View File
@@ -0,0 +1,360 @@
#include "uMod_Main.h"
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DCubeTexture9::QueryInterface(REFIID riid, void** ppvObj)
{
if (riid == IID_IDirect3D9) {
// This function should never be called with IID_IDirect3D9 by the game
// thus this call comes from our own dll to ask for the texture type
// 0x01000000L == uMod_IDirect3DTexture9
// 0x01000001L == uMod_IDirect3DVolumeTexture9
// 0x01000002L == uMod_IDirect3DCubeTexture9
*ppvObj = this;
return 0x01000002L;
}
HRESULT hRes;
if (CrossRef_D3Dtex != nullptr) {
hRes = CrossRef_D3Dtex->m_D3Dtex->QueryInterface(riid, ppvObj);
if (*ppvObj == CrossRef_D3Dtex->m_D3Dtex) {
*ppvObj = this;
}
}
else {
hRes = m_D3Dtex->QueryInterface(riid, ppvObj);
if (*ppvObj == m_D3Dtex) {
*ppvObj = this;
}
}
return hRes;
}
//this function yields for the non switched texture object
ULONG APIENTRY uMod_IDirect3DCubeTexture9::AddRef()
{
if (FAKE) {
return 1; //bug, this case should never happen
}
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->AddRef();
}
return m_D3Dtex->AddRef();
}
//this function yields for the non switched texture object
ULONG APIENTRY uMod_IDirect3DCubeTexture9::Release()
{
Message("uMod_IDirect3DCubeTexture9::Release(): %lu\n", this);
void* cpy;
const long ret = m_D3Ddev->QueryInterface(IID_IDirect3DTexture9, &cpy);
ULONG count;
if (FAKE) {
UnswitchTextures(this);
count = m_D3Dtex->Release(); //count must be zero, cause we don't call AddRef of fake_textures
}
else {
if (CrossRef_D3Dtex != nullptr) //if this texture is switched with a fake texture
{
uMod_IDirect3DCubeTexture9* fake_texture = CrossRef_D3Dtex;
count = fake_texture->m_D3Dtex->Release(); //release the original texture
if (count == 0) //if texture is released we switch the textures back
{
UnswitchTextures(this);
if (ret == 0x01000000L) {
if (static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetSingleCubeTexture() != fake_texture) {
fake_texture->Release(); // we release the fake texture
}
}
else {
if (static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->GetSingleCubeTexture() != fake_texture) {
fake_texture->Release(); // we release the fake texture
}
}
}
}
else {
count = m_D3Dtex->Release();
}
}
if (count == 0) //if this texture is released, we clean up
{
// if this texture is the LastCreatedTexture, the next time LastCreatedTexture would be added,
// the hash of a non existing texture would be calculated
if (ret == 0x01000000L) {
if (static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetLastCreatedCubeTexture() == this) {
static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->SetLastCreatedCubeTexture(nullptr);
}
else {
static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client
}
}
else {
if (static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->GetLastCreatedCubeTexture() == this) {
static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->SetLastCreatedCubeTexture(nullptr);
}
else {
static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client
}
}
delete(this);
}
return count;
}
HRESULT APIENTRY uMod_IDirect3DCubeTexture9::GetDevice(IDirect3DDevice9** ppDevice)
{
*ppDevice = m_D3Ddev;
return D3D_OK;
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DCubeTexture9::SetPrivateData(REFGUID refguid,CONST void* pData, DWORD SizeOfData, DWORD Flags)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->SetPrivateData(refguid, pData, SizeOfData, Flags);
}
return m_D3Dtex->SetPrivateData(refguid, pData, SizeOfData, Flags);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DCubeTexture9::GetPrivateData(REFGUID refguid, void* pData, DWORD* pSizeOfData)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->GetPrivateData(refguid, pData, pSizeOfData);
}
return m_D3Dtex->GetPrivateData(refguid, pData, pSizeOfData);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DCubeTexture9::FreePrivateData(REFGUID refguid)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->FreePrivateData(refguid);
}
return m_D3Dtex->FreePrivateData(refguid);
}
DWORD APIENTRY uMod_IDirect3DCubeTexture9::SetPriority(DWORD PriorityNew)
{
return m_D3Dtex->SetPriority(PriorityNew);
}
DWORD APIENTRY uMod_IDirect3DCubeTexture9::GetPriority()
{
return m_D3Dtex->GetPriority();
}
void APIENTRY uMod_IDirect3DCubeTexture9::PreLoad()
{
m_D3Dtex->PreLoad();
}
D3DRESOURCETYPE APIENTRY uMod_IDirect3DCubeTexture9::GetType()
{
return m_D3Dtex->GetType();
}
DWORD APIENTRY uMod_IDirect3DCubeTexture9::SetLOD(DWORD LODNew)
{
return m_D3Dtex->SetLOD(LODNew);
}
DWORD APIENTRY uMod_IDirect3DCubeTexture9::GetLOD()
{
return m_D3Dtex->GetLOD();
}
DWORD APIENTRY uMod_IDirect3DCubeTexture9::GetLevelCount()
{
return m_D3Dtex->GetLevelCount();
}
HRESULT APIENTRY uMod_IDirect3DCubeTexture9::SetAutoGenFilterType(D3DTEXTUREFILTERTYPE FilterType)
{
return m_D3Dtex->SetAutoGenFilterType(FilterType);
}
D3DTEXTUREFILTERTYPE APIENTRY uMod_IDirect3DCubeTexture9::GetAutoGenFilterType()
{
return m_D3Dtex->GetAutoGenFilterType();
}
void APIENTRY uMod_IDirect3DCubeTexture9::GenerateMipSubLevels()
{
m_D3Dtex->GenerateMipSubLevels();
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DCubeTexture9::AddDirtyRect(D3DCUBEMAP_FACES FaceType, CONST RECT* pDirtyRect)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->AddDirtyRect(FaceType, pDirtyRect);
}
return m_D3Dtex->AddDirtyRect(FaceType, pDirtyRect);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DCubeTexture9::GetLevelDesc(UINT Level, D3DSURFACE_DESC* pDesc)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->GetLevelDesc(Level, pDesc);
}
return m_D3Dtex->GetLevelDesc(Level, pDesc);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DCubeTexture9::GetCubeMapSurface(D3DCUBEMAP_FACES FaceType, UINT Level, IDirect3DSurface9** ppCubeMapSurface)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->GetCubeMapSurface(FaceType, Level, ppCubeMapSurface);
}
return m_D3Dtex->GetCubeMapSurface(FaceType, Level, ppCubeMapSurface);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DCubeTexture9::LockRect(D3DCUBEMAP_FACES FaceType, UINT Level, D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect, DWORD Flags)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->LockRect(FaceType, Level, pLockedRect, pRect, Flags);
}
return m_D3Dtex->LockRect(FaceType, Level, pLockedRect, pRect, Flags);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DCubeTexture9::UnlockRect(D3DCUBEMAP_FACES FaceType, UINT Level)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->UnlockRect(FaceType, Level);
}
return m_D3Dtex->UnlockRect(FaceType, Level);
}
int uMod_IDirect3DCubeTexture9::GetHash(MyTypeHash& hash)
{
hash = 0u;
if (FAKE) {
return RETURN_BAD_ARGUMENT;
}
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;
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;
}
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)
{
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;
}
if (pResolvedSurface->LockRect(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) {
pResolvedSurface->Release();
Message("uMod_IDirect3DCubeTexture9::GetHash() Failed: LockRect 2\n");
return RETURN_LockRect_FAILED;
}
}
const int size = (GetBitsFromFormat(desc.Format) * desc.Width * desc.Height) / 8;
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
*/
if (pResolvedSurface != nullptr) {
pResolvedSurface->UnlockRect();
pResolvedSurface->Release();
}
else {
pTexture->UnlockRect(D3DCUBEMAP_FACE_POSITIVE_X, 0); //unlock the raw data
}
Message("uMod_IDirect3DCubeTexture9::GetHash() %#lX (%d %d) %d = %d\n", hash, desc.Width, desc.Height, desc.Format, size);
return RETURN_OK;
}
File diff suppressed because it is too large Load Diff
+95
View File
@@ -0,0 +1,95 @@
#include "uMod_Main.h"
#define uMod_IDirect3DDevice9 uMod_IDirect3DDevice9Ex
#define IDirect3DDevice9 IDirect3DDevice9Ex
#define m_pIDirect3DDevice9 m_pIDirect3DDevice9Ex
#define RETURN_QueryInterface 0x01000001L
#define PRE_MESSAGE "uMod_IDirect3DDevice9Ex"
// ReSharper disable once CppUnusedIncludeDirective
#include "uMod_IDirect3DDevice9.cpp"
HRESULT __stdcall uMod_IDirect3DDevice9Ex::CheckDeviceState(HWND hWindow)
{
return m_pIDirect3DDevice9Ex->CheckDeviceState(hWindow);
}
HRESULT __stdcall uMod_IDirect3DDevice9Ex::CheckResourceResidency(IDirect3DResource9** ppResourceArray, UINT32 NumResources)
{
return m_pIDirect3DDevice9Ex->CheckResourceResidency(ppResourceArray, NumResources);
}
HRESULT __stdcall uMod_IDirect3DDevice9Ex::ComposeRects(IDirect3DSurface9* pSource, IDirect3DSurface9* pDestination, IDirect3DVertexBuffer9* pSrcRectDescriptors, UINT NumRects, IDirect3DVertexBuffer9* pDstRectDescriptors, D3DCOMPOSERECTSOP Operation,
INT XOffset, INT YOffset)
{
return m_pIDirect3DDevice9Ex->ComposeRects(pSource, pDestination, pSrcRectDescriptors, NumRects, pDstRectDescriptors, Operation, XOffset, YOffset);
}
HRESULT __stdcall uMod_IDirect3DDevice9Ex::CreateDepthStencilSurfaceEx(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle, DWORD Usage)
{
return m_pIDirect3DDevice9Ex->CreateDepthStencilSurfaceEx(Width, Height, Format, MultiSample, MultisampleQuality, Discard, ppSurface, pSharedHandle, Usage);
}
HRESULT __stdcall uMod_IDirect3DDevice9Ex::CreateOffscreenPlainSurfaceEx(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle, DWORD Usage)
{
return m_pIDirect3DDevice9Ex->CreateOffscreenPlainSurfaceEx(Width, Height, Format, Pool, ppSurface, pSharedHandle, Usage);
}
HRESULT __stdcall uMod_IDirect3DDevice9Ex::CreateRenderTargetEx(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle, DWORD Usage)
{
return m_pIDirect3DDevice9Ex->CreateRenderTargetEx(Width, Height, Format, MultiSample, MultisampleQuality, Lockable, ppSurface, pSharedHandle, Usage);
}
HRESULT __stdcall uMod_IDirect3DDevice9Ex::GetDisplayModeEx(UINT iSwapChain, D3DDISPLAYMODEEX* pMode, D3DDISPLAYROTATION* pRotation)
{
return m_pIDirect3DDevice9Ex->GetDisplayModeEx(iSwapChain, pMode, pRotation);
}
HRESULT __stdcall uMod_IDirect3DDevice9Ex::GetGPUThreadPriority(INT* pPriority)
{
return m_pIDirect3DDevice9Ex->GetGPUThreadPriority(pPriority);
}
HRESULT __stdcall uMod_IDirect3DDevice9Ex::GetMaximumFrameLatency(UINT* pMaxLatency)
{
return m_pIDirect3DDevice9Ex->GetMaximumFrameLatency(pMaxLatency);
}
HRESULT __stdcall uMod_IDirect3DDevice9Ex::PresentEx(const RECT* pSourceRect, const RECT* pDestRect, HWND hDestWindowOverride, const RGNDATA* pDirtyRegion, DWORD dwFlags)
{
return m_pIDirect3DDevice9Ex->PresentEx(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags);
}
HRESULT __stdcall uMod_IDirect3DDevice9Ex::ResetEx(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode)
{
return m_pIDirect3DDevice9Ex->ResetEx(pPresentationParameters, pFullscreenDisplayMode);
}
HRESULT __stdcall uMod_IDirect3DDevice9Ex::SetConvolutionMonoKernel(UINT Width, UINT Height, float* RowWeights, float* ColumnWeights)
{
return m_pIDirect3DDevice9Ex->SetConvolutionMonoKernel(Width, Height, RowWeights, ColumnWeights);
}
HRESULT __stdcall uMod_IDirect3DDevice9Ex::SetGPUThreadPriority(INT pPriority)
{
return m_pIDirect3DDevice9Ex->SetGPUThreadPriority(pPriority);
}
HRESULT __stdcall uMod_IDirect3DDevice9Ex::SetMaximumFrameLatency(UINT pMaxLatency)
{
return m_pIDirect3DDevice9Ex->SetMaximumFrameLatency(pMaxLatency);
}
/*
HRESULT __stdcall uMod_IDirect3DDevice9Ex::TestCooperativeLevel()
{
return(m_pIDirect3DDevice9Ex->TestCooperativeLevel();
}
*/
HRESULT __stdcall uMod_IDirect3DDevice9Ex::WaitForVBlank(UINT SwapChainIndex)
{
return m_pIDirect3DDevice9Ex->WaitForVBlank(SwapChainIndex);
}
+354
View File
@@ -0,0 +1,354 @@
#include "uMod_Main.h"
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DTexture9::QueryInterface(REFIID riid, void** ppvObj)
{
if (riid == IID_IDirect3D9) {
// This function should never be called with IID_IDirect3D9 by the game
// thus this call comes from our own dll to ask for the texture type
// 0x01000000L == uMod_IDirect3DTexture9
// 0x01000001L == uMod_IDirect3DVolumeTexture9
// 0x01000002L == uMod_IDirect3DCubeTexture9
*ppvObj = this;
return 0x01000000L;
}
HRESULT hRes;
if (CrossRef_D3Dtex != nullptr) {
hRes = CrossRef_D3Dtex->m_D3Dtex->QueryInterface(riid, ppvObj);
if (*ppvObj == CrossRef_D3Dtex->m_D3Dtex) {
*ppvObj = this;
}
}
else {
hRes = m_D3Dtex->QueryInterface(riid, ppvObj);
if (*ppvObj == m_D3Dtex) {
*ppvObj = this;
}
}
return hRes;
}
//this function yields for the non switched texture object
ULONG APIENTRY uMod_IDirect3DTexture9::AddRef()
{
if (FAKE) {
return 1; //bug, this case should never happen
}
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->AddRef();
}
return m_D3Dtex->AddRef();
}
//this function yields for the non switched texture object
ULONG APIENTRY uMod_IDirect3DTexture9::Release()
{
Message("uMod_IDirect3DTexture9::Release(): %lu\n", this);
void* cpy;
const long ret = m_D3Ddev->QueryInterface(IID_IDirect3DTexture9, &cpy);
ULONG count;
if (FAKE) {
UnswitchTextures(this);
count = m_D3Dtex->Release(); //count must be zero, cause we don't call AddRef of fake_textures
}
else {
if (CrossRef_D3Dtex != nullptr) //if this texture is switched with a fake texture
{
uMod_IDirect3DTexture9* fake_texture = CrossRef_D3Dtex;
count = fake_texture->m_D3Dtex->Release(); //release the original texture
if (count == 0) //if texture is released we switch the textures back
{
UnswitchTextures(this);
if (ret == 0x01000000L) {
if (static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetSingleTexture() != fake_texture) {
fake_texture->Release(); // we release the fake texture
}
}
else {
if (static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->GetSingleTexture() != fake_texture) {
fake_texture->Release(); // we release the fake texture
}
}
}
}
else {
count = m_D3Dtex->Release();
}
}
if (count == 0) //if this texture is released, we clean up
{
// if this texture is the LastCreatedTexture, the next time LastCreatedTexture would be added,
// the hash of a non existing texture would be calculated
if (ret == 0x01000000L) {
if (static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetLastCreatedTexture() == this) {
static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->SetLastCreatedTexture(nullptr);
}
else {
static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client
}
}
else {
if (static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->GetLastCreatedTexture() == this) {
static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->SetLastCreatedTexture(nullptr);
}
else {
static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client
}
}
delete(this);
}
Message("uMod_IDirect3DTexture9::Release() end: %lu\n", this);
return count;
}
HRESULT APIENTRY uMod_IDirect3DTexture9::GetDevice(IDirect3DDevice9** ppDevice)
{
*ppDevice = m_D3Ddev;
return D3D_OK;
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DTexture9::SetPrivateData(REFGUID refguid,CONST void* pData, DWORD SizeOfData, DWORD Flags)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->SetPrivateData(refguid, pData, SizeOfData, Flags);
}
return m_D3Dtex->SetPrivateData(refguid, pData, SizeOfData, Flags);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DTexture9::GetPrivateData(REFGUID refguid, void* pData, DWORD* pSizeOfData)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->GetPrivateData(refguid, pData, pSizeOfData);
}
return m_D3Dtex->GetPrivateData(refguid, pData, pSizeOfData);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DTexture9::FreePrivateData(REFGUID refguid)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->FreePrivateData(refguid);
}
return m_D3Dtex->FreePrivateData(refguid);
}
DWORD APIENTRY uMod_IDirect3DTexture9::SetPriority(DWORD PriorityNew)
{
return m_D3Dtex->SetPriority(PriorityNew);
}
DWORD APIENTRY uMod_IDirect3DTexture9::GetPriority()
{
return m_D3Dtex->GetPriority();
}
void APIENTRY uMod_IDirect3DTexture9::PreLoad()
{
m_D3Dtex->PreLoad();
}
D3DRESOURCETYPE APIENTRY uMod_IDirect3DTexture9::GetType()
{
return m_D3Dtex->GetType();
}
DWORD APIENTRY uMod_IDirect3DTexture9::SetLOD(DWORD LODNew)
{
return m_D3Dtex->SetLOD(LODNew);
}
DWORD APIENTRY uMod_IDirect3DTexture9::GetLOD()
{
return m_D3Dtex->GetLOD();
}
DWORD APIENTRY uMod_IDirect3DTexture9::GetLevelCount()
{
return m_D3Dtex->GetLevelCount();
}
HRESULT APIENTRY uMod_IDirect3DTexture9::SetAutoGenFilterType(D3DTEXTUREFILTERTYPE FilterType)
{
return m_D3Dtex->SetAutoGenFilterType(FilterType);
}
D3DTEXTUREFILTERTYPE APIENTRY uMod_IDirect3DTexture9::GetAutoGenFilterType()
{
return m_D3Dtex->GetAutoGenFilterType();
}
void APIENTRY uMod_IDirect3DTexture9::GenerateMipSubLevels()
{
m_D3Dtex->GenerateMipSubLevels();
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DTexture9::GetLevelDesc(UINT Level, D3DSURFACE_DESC* pDesc)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->GetLevelDesc(Level, pDesc);
}
return m_D3Dtex->GetLevelDesc(Level, pDesc);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DTexture9::GetSurfaceLevel(UINT Level, IDirect3DSurface9** ppSurfaceLevel)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->GetSurfaceLevel(Level, ppSurfaceLevel);
}
return m_D3Dtex->GetSurfaceLevel(Level, ppSurfaceLevel);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DTexture9::LockRect(UINT Level, D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect, DWORD Flags)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->LockRect(Level, pLockedRect, pRect, Flags);
}
return m_D3Dtex->LockRect(Level, pLockedRect, pRect, Flags);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DTexture9::UnlockRect(UINT Level)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->UnlockRect(Level);
}
return m_D3Dtex->UnlockRect(Level);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DTexture9::AddDirtyRect(CONST RECT* pDirtyRect)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->AddDirtyRect(pDirtyRect);
}
return m_D3Dtex->AddDirtyRect(pDirtyRect);
}
int uMod_IDirect3DTexture9::GetHash(MyTypeHash& hash)
{
hash = 0u;
if (FAKE) {
return RETURN_BAD_ARGUMENT;
}
IDirect3DTexture9* pTexture = m_D3Dtex;
if (CrossRef_D3Dtex != nullptr) {
pTexture = CrossRef_D3Dtex->m_D3Dtex;
}
IDirect3DSurface9* pOffscreenSurface = nullptr;
//IDirect3DTexture9 *pOffscreenTexture = NULL;
IDirect3DSurface9* pResolvedSurface = nullptr;
D3DLOCKED_RECT d3dlr;
D3DSURFACE_DESC desc;
if (pTexture->GetLevelDesc(0, &desc) != D3D_OK) //get the format and the size of the texture
{
Message("uMod_IDirect3DTexture9::GetHash() Failed: GetLevelDesc \n");
return RETURN_GetLevelDesc_FAILED;
}
Message("uMod_IDirect3DTexture9::GetHash() (%d %d) %d\n", desc.Width, desc.Height, desc.Format);
if (desc.Pool == D3DPOOL_DEFAULT) //get the raw data of the texture
{
//Message("uMod_IDirect3DTexture9::GetHash() (D3DPOOL_DEFAULT)\n");
IDirect3DSurface9* pSurfaceLevel_orig = nullptr;
if (pTexture->GetSurfaceLevel(0, &pSurfaceLevel_orig) != D3D_OK) {
Message("uMod_IDirect3DTexture9::GetHash() Failed: GetSurfaceLevel 1 (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED;
}
if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) {
//Message("uMod_IDirect3DTexture9::GetHash() MultiSampleType\n");
if (D3D_OK != m_D3Ddev->CreateRenderTarget(desc.Width, desc.Height, desc.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pResolvedSurface, nullptr)) {
pSurfaceLevel_orig->Release();
Message("uMod_IDirect3DTexture9::GetHash() Failed: CreateRenderTarget (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED;
}
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;
}
pSurfaceLevel_orig = pResolvedSurface;
}
if (D3D_OK != m_D3Ddev->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pOffscreenSurface, nullptr)) {
pSurfaceLevel_orig->Release();
if (pResolvedSurface != nullptr) {
pResolvedSurface->Release();
}
Message("uMod_IDirect3DTexture9::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 != nullptr) {
pResolvedSurface->Release();
}
pOffscreenSurface->Release();
Message("uMod_IDirect3DTexture9::GetHash() Failed: GetRenderTargetData (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED;
}
pSurfaceLevel_orig->Release();
if (pOffscreenSurface->LockRect(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) {
if (pResolvedSurface != nullptr) {
pResolvedSurface->Release();
}
pOffscreenSurface->Release();
Message("uMod_IDirect3DTexture9::GetHash() Failed: LockRect (D3DPOOL_DEFAULT)\n");
return RETURN_LockRect_FAILED;
}
}
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;
}
if (pResolvedSurface->LockRect(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) {
pResolvedSurface->Release();
Message("uMod_IDirect3DTexture9::GetHash() Failed: LockRect 2\n");
return RETURN_LockRect_FAILED;
}
}
const int size = (GetBitsFromFormat(desc.Format) * desc.Width * desc.Height) / 8;
hash = GetCRC32(static_cast<char*>(d3dlr.pBits), size); //calculate the crc32 of the texture
if (pOffscreenSurface != nullptr) {
pOffscreenSurface->UnlockRect();
pOffscreenSurface->Release();
if (pResolvedSurface != nullptr) {
pResolvedSurface->Release();
}
}
else if (pResolvedSurface != nullptr) {
pResolvedSurface->UnlockRect();
pResolvedSurface->Release();
}
else {
pTexture->UnlockRect(0);
}
Message("uMod_IDirect3DTexture9::GetHash() %#lX (%d %d) %d = %d\n", hash, desc.Width, desc.Height, desc.Format, size);
return RETURN_OK;
}
+386
View File
@@ -0,0 +1,386 @@
#include "uMod_Main.h"
HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::QueryInterface(REFIID riid, void** ppvObj)
{
if (riid == IID_IDirect3D9) {
// This function should never be called with IID_IDirect3D9 by the game
// thus this call comes from our own dll to ask for the texture type
// 0x01000000L == uMod_IDirect3DTexture9
// 0x01000001L == uMod_IDirect3DVolumeTexture9
// 0x01000002L == uMod_IDirect3DCubeTexture9
*ppvObj = this;
return 0x01000001L;
}
HRESULT hRes;
if (CrossRef_D3Dtex != nullptr) {
hRes = CrossRef_D3Dtex->m_D3Dtex->QueryInterface(riid, ppvObj);
if (*ppvObj == CrossRef_D3Dtex->m_D3Dtex) {
*ppvObj = this;
}
}
else {
hRes = m_D3Dtex->QueryInterface(riid, ppvObj);
if (*ppvObj == m_D3Dtex) {
*ppvObj = this;
}
}
return hRes;
}
//this function yields for the non switched texture object
ULONG APIENTRY uMod_IDirect3DVolumeTexture9::AddRef()
{
if (FAKE) {
return 1; //bug, this case should never happen
}
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->AddRef();
}
return m_D3Dtex->AddRef();
}
//this function yields for the non switched texture object
ULONG APIENTRY uMod_IDirect3DVolumeTexture9::Release()
{
Message("uMod_IDirect3DVolumeTexture9::Release(): %lu\n", this);
void* cpy;
const long ret = m_D3Ddev->QueryInterface(IID_IDirect3DTexture9, &cpy);
ULONG count;
if (FAKE) {
UnswitchTextures(this);
count = m_D3Dtex->Release(); //count must be zero, cause we don't call AddRef of fake_textures
}
else {
if (CrossRef_D3Dtex != nullptr) //if this texture is switched with a fake texture
{
uMod_IDirect3DVolumeTexture9* fake_texture = CrossRef_D3Dtex;
count = fake_texture->m_D3Dtex->Release(); //release the original texture
if (count == 0) //if texture is released we switch the textures back
{
UnswitchTextures(this);
if (ret == 0x01000000L) {
if (static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetSingleVolumeTexture() != fake_texture) {
fake_texture->Release(); // we release the fake texture
}
}
else {
if (static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->GetSingleVolumeTexture() != fake_texture) {
fake_texture->Release(); // we release the fake texture
}
}
}
}
else {
count = m_D3Dtex->Release();
}
}
if (count == 0) //if this texture is released, we clean up
{
// if this texture is the LastCreatedTexture, the next time LastCreatedTexture would be added,
// the hash of a non existing texture would be calculated
if (ret == 0x01000000L) {
if (static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetLastCreatedVolumeTexture() == this) {
static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->SetLastCreatedVolumeTexture(nullptr);
}
else {
static_cast<uMod_IDirect3DDevice9*>(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client
}
}
else {
if (static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->GetLastCreatedVolumeTexture() == this) {
static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->SetLastCreatedVolumeTexture(nullptr);
}
else {
static_cast<uMod_IDirect3DDevice9Ex*>(m_D3Ddev)->GetuMod_Client()->RemoveTexture(this); // remove this texture from the texture client
}
}
delete(this);
}
return count;
}
HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::GetDevice(IDirect3DDevice9** ppDevice)
{
*ppDevice = m_D3Ddev;
return D3D_OK;
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::SetPrivateData(REFGUID refguid,CONST void* pData, DWORD SizeOfData, DWORD Flags)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->SetPrivateData(refguid, pData, SizeOfData, Flags);
}
return m_D3Dtex->SetPrivateData(refguid, pData, SizeOfData, Flags);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::GetPrivateData(REFGUID refguid, void* pData, DWORD* pSizeOfData)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->GetPrivateData(refguid, pData, pSizeOfData);
}
return m_D3Dtex->GetPrivateData(refguid, pData, pSizeOfData);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::FreePrivateData(REFGUID refguid)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->FreePrivateData(refguid);
}
return m_D3Dtex->FreePrivateData(refguid);
}
DWORD APIENTRY uMod_IDirect3DVolumeTexture9::SetPriority(DWORD PriorityNew)
{
return m_D3Dtex->SetPriority(PriorityNew);
}
DWORD APIENTRY uMod_IDirect3DVolumeTexture9::GetPriority()
{
return m_D3Dtex->GetPriority();
}
void APIENTRY uMod_IDirect3DVolumeTexture9::PreLoad()
{
m_D3Dtex->PreLoad();
}
D3DRESOURCETYPE APIENTRY uMod_IDirect3DVolumeTexture9::GetType()
{
return m_D3Dtex->GetType();
}
DWORD APIENTRY uMod_IDirect3DVolumeTexture9::SetLOD(DWORD LODNew)
{
return m_D3Dtex->SetLOD(LODNew);
}
DWORD APIENTRY uMod_IDirect3DVolumeTexture9::GetLOD()
{
return m_D3Dtex->GetLOD();
}
DWORD APIENTRY uMod_IDirect3DVolumeTexture9::GetLevelCount()
{
return m_D3Dtex->GetLevelCount();
}
HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::SetAutoGenFilterType(D3DTEXTUREFILTERTYPE FilterType)
{
return m_D3Dtex->SetAutoGenFilterType(FilterType);
}
D3DTEXTUREFILTERTYPE APIENTRY uMod_IDirect3DVolumeTexture9::GetAutoGenFilterType()
{
return m_D3Dtex->GetAutoGenFilterType();
}
void APIENTRY uMod_IDirect3DVolumeTexture9::GenerateMipSubLevels()
{
m_D3Dtex->GenerateMipSubLevels();
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::AddDirtyBox(CONST D3DBOX* pDirtyBox)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->AddDirtyBox(pDirtyBox);
}
return m_D3Dtex->AddDirtyBox(pDirtyBox);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::GetLevelDesc(UINT Level, D3DVOLUME_DESC* pDesc)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->GetLevelDesc(Level, pDesc);
}
return m_D3Dtex->GetLevelDesc(Level, pDesc);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::GetVolumeLevel(UINT Level, IDirect3DVolume9** ppVolumeLevel)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->GetVolumeLevel(Level, ppVolumeLevel);
}
return m_D3Dtex->GetVolumeLevel(Level, ppVolumeLevel);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::LockBox(UINT Level, D3DLOCKED_BOX* pLockedVolume, CONST D3DBOX* pBox, DWORD Flags)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->LockBox(Level, pLockedVolume, pBox, Flags);
}
return m_D3Dtex->LockBox(Level, pLockedVolume, pBox, Flags);
}
//this function yields for the non switched texture object
HRESULT APIENTRY uMod_IDirect3DVolumeTexture9::UnlockBox(UINT Level)
{
if (CrossRef_D3Dtex != nullptr) {
return CrossRef_D3Dtex->m_D3Dtex->UnlockBox(Level);
}
return m_D3Dtex->UnlockBox(Level);
}
int uMod_IDirect3DVolumeTexture9::GetHash(MyTypeHash& hash)
{
hash = 0u;
if (FAKE) {
return RETURN_BAD_ARGUMENT;
}
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;
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;
}
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;
}
if (pResolvedSurface->LockBox(&d3dlr, nullptr, D3DLOCK_READONLY) != D3D_OK) {
pResolvedSurface->Release();
Message("uMod_IDirect3DVolumeTexture9::GetHash() Failed: LockRect 2\n");
return RETURN_LockRect_FAILED;
}
}
const int size = (GetBitsFromFormat(desc.Format) * desc.Width * desc.Height * desc.Depth) / 8;
hash = GetCRC32(static_cast<char*>(d3dlr.pBits), size); //calculate the crc32 of the texture
if (pResolvedSurface != nullptr) {
pResolvedSurface->UnlockBox();
pResolvedSurface->Release();
}
else {
pTexture->UnlockBox(0);
}
Message("uMod_IDirect3DVolumeTexture9::GetHash() %#lX (%d %d) %d = %d\n", hash, desc.Width, desc.Height, desc.Format, size);
return RETURN_OK;
}
+995
View File
@@ -0,0 +1,995 @@
#include "uMod_Main.h"
uMod_TextureClient::uMod_TextureClient(uMod_TextureServer* server, IDirect3DDevice9* device)
{
Message("uMod_TextureClient::uMod_TextureClient(): %lu\n", this);
Server = server;
D3D9Device = device;
BoolSaveAllTextures = false;
BoolSaveSingleTexture = false;
KeyBack = 0;
KeySave = 0;
KeyNext = 0;
SavePath[0] = 0;
GameName[0] = 0;
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(): %lu\n", this);
if (Server != nullptr) {
Server->RemoveClient(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( %lu): %lu (thread: %lu)\n", pTexture, this, GetCurrentThreadId());
MyTypeHash hash;
if (const int ret = pTexture->GetHash(hash)) {
return ret;
}
pTexture->Hash = hash;
if (BoolSaveAllTextures) {
SaveTexture(pTexture);
}
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: %lu): %lu (thread: %lu)\n", pTexture, this, GetCurrentThreadId());
MyTypeHash hash;
if (const int ret = pTexture->GetHash(hash)) {
return ret;
}
pTexture->Hash = hash;
if (BoolSaveAllTextures) {
SaveTexture(pTexture);
}
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: %lu): %lu (thread: %lu)\n", pTexture, this, GetCurrentThreadId());
MyTypeHash hash;
if (const int ret = pTexture->GetHash(hash)) {
return ret;
}
pTexture->Hash = hash;
if (BoolSaveAllTextures) {
SaveTexture(pTexture);
}
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( %lu, %#lX): %lu\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 %lu, %#lX): %lu\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 %lu, %#lX): %lu\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::SaveAllTextures(bool val)
{
Message("uMod_TextureClient::SaveAllTextures( %d): %lu\n", val, this);
BoolSaveAllTextures = val;
return RETURN_OK;
}
int uMod_TextureClient::SaveSingleTexture(bool val)
{
Message("uMod_TextureClient::SaveSingleTexture( %d): %lu\n", val, this);
if (BoolSaveSingleTexture && !val) //if BoolSaveSingleTexture is set to false and was previously true we switch the SingleTexture back
{
uMod_IDirect3DTexture9* pTexture;
void* cpy;
const long ret = D3D9Device->QueryInterface(IID_IDirect3DTexture9, &cpy);
if (ret == 0x01000000L) {
pTexture = static_cast<uMod_IDirect3DDevice9*>(D3D9Device)->GetSingleTexture(); //this texture must no be added twice
}
else {
pTexture = static_cast<uMod_IDirect3DDevice9Ex*>(D3D9Device)->GetSingleTexture(); //this texture must no be added twice
}
if (pTexture != nullptr) {
UnswitchTextures(pTexture);
}
}
BoolSaveSingleTexture = val;
return RETURN_OK;
}
int uMod_TextureClient::SetSaveDirectory(wchar_t* dir)
{
Message("uMod_TextureClient::SetSaveDirectory( %ls): %lu\n", dir, this);
int i = 0;
for (i = 0; i < MAX_PATH && (dir[i]); i++) {
SavePath[i] = dir[i];
}
if (i == MAX_PATH) {
SavePath[0] = 0;
return RETURN_BAD_ARGUMENT;
}
SavePath[i] = 0;
return RETURN_OK;
}
int uMod_TextureClient::SetGameName(wchar_t* name)
{
Message("uMod_TextureClient::SetGameName( %ls): %lu\n", name, this);
int i = 0;
for (i = 0; i < MAX_PATH && (name[i]); i++) {
GameName[i] = name[i];
}
if (i == MAX_PATH) {
GameName[0] = 0;
return RETURN_BAD_ARGUMENT;
}
GameName[i] = 0;
return RETURN_OK;
}
int uMod_TextureClient::SaveTexture(uMod_IDirect3DTexture9* pTexture)
{
if (pTexture == nullptr) {
return RETURN_BAD_ARGUMENT;
}
if (SavePath[0] == 0) {
Message("uMod_TextureClient::SaveTexture( %#lX, %lu): %lu, SavePath not set\n", pTexture->Hash, pTexture->m_D3Dtex, this);
return RETURN_TEXTURE_NOT_SAVED;
}
wchar_t file[MAX_PATH];
if (GameName[0]) {
swprintf_s(file, MAX_PATH, L"%ls\\%ls_T_%#lX.dds", SavePath, GameName, pTexture->Hash);
}
else {
swprintf_s(file, MAX_PATH, L"%ls\\T_%#lX.dds", SavePath, pTexture->Hash);
}
Message("uMod_TextureClient::SaveTexture( %ls): %lu\n", file, this);
if (D3D_OK != D3DXSaveTextureToFileW(file, D3DXIFF_DDS, pTexture->m_D3Dtex, nullptr)) {
return RETURN_TEXTURE_NOT_SAVED;
}
return RETURN_OK;
}
int uMod_TextureClient::SaveTexture(uMod_IDirect3DVolumeTexture9* pTexture)
{
if (pTexture == nullptr) {
return RETURN_BAD_ARGUMENT;
}
if (SavePath[0] == 0) {
Message("uMod_TextureClient::SaveTexture( %#lX, %lu): %lu, SavePath not set\n", pTexture->Hash, pTexture->m_D3Dtex, this);
return RETURN_TEXTURE_NOT_SAVED;
}
wchar_t file[MAX_PATH];
if (GameName[0]) {
swprintf_s(file, MAX_PATH, L"%ls\\%ls_V_%#lX.dds", SavePath, GameName, pTexture->Hash);
}
else {
swprintf_s(file, MAX_PATH, L"%ls\\V_%#lX.dds", SavePath, pTexture->Hash);
}
Message("uMod_TextureClient::SaveTexture( %ls): %lu\n", file, this);
if (D3D_OK != D3DXSaveTextureToFileW(file, D3DXIFF_DDS, pTexture->m_D3Dtex, nullptr)) {
return RETURN_TEXTURE_NOT_SAVED;
}
return RETURN_OK;
}
int uMod_TextureClient::SaveTexture(uMod_IDirect3DCubeTexture9* pTexture)
{
if (pTexture == nullptr) {
return RETURN_BAD_ARGUMENT;
}
if (SavePath[0] == 0) {
Message("uMod_TextureClient::SaveTexture( %#lX, %lu): %lu, SavePath not set\n", pTexture->Hash, pTexture->m_D3Dtex, this);
return RETURN_TEXTURE_NOT_SAVED;
}
wchar_t file[MAX_PATH];
if (GameName[0]) {
swprintf_s(file, MAX_PATH, L"%ls\\%ls_C_%#lX.dds", SavePath, GameName, pTexture->Hash);
}
else {
swprintf_s(file, MAX_PATH, L"%ls\\C_%#lX.dds", SavePath, pTexture->Hash);
}
Message("uMod_TextureClient::SaveTexture( %ls): %lu\n", file, this);
if (D3D_OK != D3DXSaveTextureToFileW(file, D3DXIFF_DDS, pTexture->m_D3Dtex, nullptr)) {
return RETURN_TEXTURE_NOT_SAVED;
}
return RETURN_OK;
}
int uMod_TextureClient::AddUpdate(TextureFileStruct* update, int number) //client must delete the update array
{
Message("AddUpdate( %lu, %d): %lu\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(): %lu\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( %lu): hash: %#lX, %lu\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 %lu): hash: %#lX, %lu\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 %lu): hash: %#lX, %lu\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( %lu, %lu, %#lX): %lu\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( %lu, %#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 %lu, %lu, %#lX): %lu\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 %lu, %#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 %lu, %lu, %#lX): %lu\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 %lu, %#lX): DONE\n", *ppTexture, file_in_memory->Hash);
return RETURN_OK;
}
+40
View File
@@ -0,0 +1,40 @@
#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;
}
+680
View File
@@ -0,0 +1,680 @@
#include "uMod_Main.h"
#include "uMod_File.h"
uMod_TextureServer::uMod_TextureServer(char* game, char* uModName)
{
Message("uMod_TextureServer(): %lu\n", this);
Mutex = CreateMutex(nullptr, false, nullptr);
Clients = nullptr;
NumberOfClients = 0;
LenghtOfClients = 0;
BoolSaveAllTextures = false;
BoolSaveSingleTexture = false;
SavePath[0] = 0;
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;
}
for (len = 0; len < MAX_PATH; len++) {
UModName[len] = uModName[len];
}
KeyBack = 0;
KeySave = 0;
KeyNext = 0;
FontColour = 0u;
TextureColour = 0u;
Pipe.In = INVALID_HANDLE_VALUE;
Pipe.Out = INVALID_HANDLE_VALUE;
}
uMod_TextureServer::~uMod_TextureServer()
{
Message("~uMod_TextureServer(): %lu\n", this);
if (Mutex != nullptr) {
CloseHandle(Mutex);
}
//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
}
if (Pipe.In != INVALID_HANDLE_VALUE) {
CloseHandle(Pipe.In);
}
Pipe.In = INVALID_HANDLE_VALUE;
if (Pipe.Out != INVALID_HANDLE_VALUE) {
CloseHandle(Pipe.Out);
}
Pipe.Out = INVALID_HANDLE_VALUE;
}
int uMod_TextureServer::AddClient(uMod_TextureClient* client, TextureFileStruct** update, int* number) // called from a client
{
Message("AddClient(%lu): %lu\n", client, this);
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_SERVER;
return ret;
}
// 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
client->SetGameName(GameName);
client->SaveAllTextures(BoolSaveAllTextures);
client->SaveSingleTexture(BoolSaveSingleTexture);
client->SetSaveDirectory(SavePath);
if (KeyBack > 0) {
client->SetKeyBack(KeyBack);
}
if (KeySave > 0) {
client->SetKeySave(KeySave);
}
if (KeyNext > 0) {
client->SetKeyNext(KeyNext);
}
if (FontColour > 0u) {
const DWORD r = FontColour >> 16 & 0xFF;
const DWORD g = FontColour >> 8 & 0xFF;
const DWORD b = FontColour & 0xFF;
client->SetFontColour(r, g, b);
}
if (TextureColour > 0u) {
const DWORD r = TextureColour >> 16 & 0xFF;
const DWORD g = TextureColour >> 8 & 0xFF;
const DWORD b = TextureColour & 0xFF;
client->SetTextureColour(r, g, b);
}
if (const int ret = PrepareUpdate(update, number)) {
return ret; // get a copy of all texture to be modded
}
if (NumberOfClients == LenghtOfClients) //allocate more memory
{
uMod_TextureClient** temp = nullptr;
try { temp = new uMod_TextureClient*[LenghtOfClients + 10]; }
catch (...) {
gl_ErrorState |= uMod_ERROR_MEMORY | uMod_ERROR_SERVER;
if (const int ret = UnlockMutex()) {
return ret;
}
return RETURN_NO_MEMORY;
}
for (int i = 0; i < LenghtOfClients; i++) {
temp[i] = Clients[i];
}
delete[] Clients;
Clients = temp;
LenghtOfClients += 10;
}
Clients[NumberOfClients++] = client;
return UnlockMutex();
}
int uMod_TextureServer::RemoveClient(uMod_TextureClient* client) // called from a client
{
Message("RemoveClient(): %lu\n", client);
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_SERVER;
return ret;
}
for (int i = 0; i < NumberOfClients; i++) {
if (client == Clients[i]) {
NumberOfClients--;
Clients[i] = Clients[NumberOfClients];
break;
}
}
return UnlockMutex();
}
int uMod_TextureServer::AddFile(char* buffer, unsigned int size, MyTypeHash hash, bool force) // called from Mainloop()
{
Message("uMod_TextureServer::AddFile( %lu %lu, %#lX, %d): %lu\n", buffer, 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_OK; // 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_OK; // 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;
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;
}
try {
temp->pData = new char[size];
}
catch (...) {
if (!new_file) {
CurrentMod.Remove(temp); // if this is a not a new file it is in the list of the CurrentMod
}
delete temp;
gl_ErrorState |= uMod_ERROR_MEMORY | uMod_ERROR_SERVER;
return RETURN_NO_MEMORY;
}
for (unsigned int i = 0; i < size; i++) {
temp->pData[i] = buffer[i];
}
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::AddFile(wchar_t* file_name, MyTypeHash hash, bool force) // called from Mainloop
// this functions does the same, but loads the file content from disk
{
Message("uMod_TextureServer::AddFile( %ls, %#lX, %d): %lu\n", file_name, hash, force, this);
TextureFileStruct* temp = nullptr;
int num = CurrentMod.GetNumber();
for (int i = 0; i < num; i++) {
if (CurrentMod[i]->Hash == hash) {
if (force) {
temp = CurrentMod[i];
break;
}
return RETURN_OK;
}
}
if (temp == nullptr) {
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;
}
return RETURN_OK;
}
}
}
FILE* file;
if (_wfopen_s(&file, file_name, L"rb") != 0) {
Message("AddFile( ): file not found\n");
return RETURN_FILE_NOT_LOADED;
}
fseek(file, 0, SEEK_END);
const unsigned int size = ftell(file);
fseek(file, 0, SEEK_SET);
bool new_file = true;
if (temp != nullptr) {
new_file = false;
delete[] temp->pData;
temp->pData = nullptr;
}
else {
new_file = true;
temp = new TextureFileStruct;
temp->Reference = -1;
}
try {
temp->pData = new char[size];
}
catch (...) {
if (!new_file) {
CurrentMod.Remove(temp);
}
delete temp;
gl_ErrorState |= uMod_ERROR_MEMORY | uMod_ERROR_SERVER;
return RETURN_NO_MEMORY;
}
const int result = fread(temp->pData, 1, size, file);
fclose(file);
if (result != size) {
delete[] temp->pData;
if (!new_file) {
CurrentMod.Remove(temp);
}
delete temp;
return RETURN_FILE_NOT_LOADED;
}
temp->Size = size;
temp->NumberOfTextures = 0;
temp->Textures = nullptr;
temp->Hash = hash;
if (new_file) {
temp->ForceReload = false;
}
else {
temp->ForceReload = force;
}
Message("End AddFile(%#lX)\n", hash);
if (new_file) {
return CurrentMod.Add(temp);
}
return RETURN_OK;
}
int uMod_TextureServer::RemoveFile(MyTypeHash hash) // called from Mainloop()
{
Message("RemoveFile( %lu): %lu\n", hash, this);
const int num = CurrentMod.GetNumber();
for (int i = 0; i < num; i++) {
if (CurrentMod[i]->Hash == hash) {
TextureFileStruct* temp = CurrentMod[i];
CurrentMod.Remove(temp);
return OldMod.Add(temp);
}
}
return RETURN_OK;
}
int uMod_TextureServer::SaveAllTextures(bool val) // called from Mainloop()
{
if (BoolSaveAllTextures == val) {
return RETURN_OK;
}
BoolSaveAllTextures = val;
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_SERVER;
return ret;
}
for (int i = 0; i < NumberOfClients; i++) {
Clients[i]->SaveAllTextures(BoolSaveAllTextures);
}
return UnlockMutex();
}
int uMod_TextureServer::SaveSingleTexture(bool val) // called from Mainloop()
{
if (BoolSaveSingleTexture == val) {
return RETURN_OK;
}
BoolSaveSingleTexture = val;
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_SERVER;
return ret;
}
for (int i = 0; i < NumberOfClients; i++) {
Clients[i]->SaveSingleTexture(BoolSaveSingleTexture);
}
return UnlockMutex();
}
int uMod_TextureServer::SetSaveDirectory(wchar_t* dir) // called from Mainloop()
{
Message("uMod_TextureServer::SetSaveDirectory( %ls): %lu\n", dir, this);
int i = 0;
for (i = 0; i < MAX_PATH && dir[i]; i++) {
SavePath[i] = dir[i];
}
if (i == MAX_PATH) {
SavePath[0] = 0;
return RETURN_BAD_ARGUMENT;
}
SavePath[i] = 0;
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_SERVER;
return ret;
}
for (int i = 0; i < NumberOfClients; i++) {
Clients[i]->SetSaveDirectory(SavePath);
}
return UnlockMutex();
}
int uMod_TextureServer::SetKeyBack(int key) // called from Mainloop()
{
if (KeyBack == key || KeySave == key || KeyNext == key) {
return RETURN_OK;
}
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_SERVER;
return ret;
}
KeyBack = key;
for (int i = 0; i < NumberOfClients; i++) {
Clients[i]->SetKeyBack(key);
}
return UnlockMutex();
}
int uMod_TextureServer::SetKeySave(int key) // called from Mainloop()
{
if (KeyBack == key || KeySave == key || KeyNext == key) {
return RETURN_OK;
}
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_SERVER;
return ret;
}
KeySave = key;
for (int i = 0; i < NumberOfClients; i++) {
Clients[i]->SetKeySave(key);
}
return UnlockMutex();
}
int uMod_TextureServer::SetKeyNext(int key) // called from Mainloop()
{
if (KeyBack == key || KeySave == key || KeyNext == key) {
return RETURN_OK;
}
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_SERVER;
return ret;
}
KeyNext = key;
for (int i = 0; i < NumberOfClients; i++) {
Clients[i]->SetKeyNext(key);
}
return UnlockMutex();
}
int uMod_TextureServer::SetFontColour(DWORD colour) // called from Mainloop()
{
if (colour == 0u) {
return RETURN_OK;
}
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_SERVER;
return ret;
}
FontColour = colour;
const DWORD r = (FontColour >> 16) & 0xFF;
const DWORD g = (FontColour >> 8) & 0xFF;
const DWORD b = (FontColour) & 0xFF;
Message("uMod_TextureServer::SetFontColour( %u %u %u): %lu\n", r, g, b, this);
for (int i = 0; i < NumberOfClients; i++) {
Clients[i]->SetFontColour(r, g, b);
}
return UnlockMutex();
}
int uMod_TextureServer::SetTextureColour(DWORD colour) // called from Mainloop()
{
if (colour == 0u) {
return RETURN_OK;
}
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_SERVER;
return ret;
}
TextureColour = colour;
const DWORD r = (TextureColour >> 16) & 0xFF;
const DWORD g = (TextureColour >> 8) & 0xFF;
const DWORD b = (TextureColour) & 0xFF;
Message("uMod_TextureServer::SetTextureColour( %u %u %u): %lu\n", r, g, b, this);
for (int i = 0; i < NumberOfClients; i++) {
Clients[i]->SetTextureColour(r, g, b);
}
return UnlockMutex();
}
int uMod_TextureServer::PropagateUpdate(uMod_TextureClient* client) // called from Mainloop(), send the update to all clients
{
Message("PropagateUpdate(%lu): %lu\n", client, this);
if (const int ret = LockMutex()) {
gl_ErrorState |= uMod_ERROR_TEXTURE;
return ret;
}
if (client != nullptr) {
TextureFileStruct* update;
int number;
if (const int ret = PrepareUpdate(&update, &number)) {
return ret;
}
client->AddUpdate(update, number);
}
else {
for (int i = 0; i < NumberOfClients; i++) {
TextureFileStruct* update;
int number;
if (const int ret = PrepareUpdate(&update, &number)) {
return ret;
}
Clients[i]->AddUpdate(update, number);
}
}
return UnlockMutex();
}
#define cpy_file_struct( a, 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(%lu, %d): %lu\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;
}
#undef cpy_file_struct
int uMod_TextureServer::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_TextureServer::UnlockMutex()
{
if (ReleaseMutex(Mutex) == 0) {
return RETURN_MUTEX_UNLOCK;
}
return RETURN_OK;
}
void uMod_TextureServer::LoadModsFromFile(char* source)
{
Message("MainLoop: searching in %s\n", source);
// Attempt to open the file
FILE* file = fopen(source, "r");
if (file) {
Message("MainLoop: found modlist.txt. Reading\n");
// Read each line from the file
char line[MAX_PATH];
while (fgets(line, sizeof(line), file) != nullptr) {
Message("MainLoop: loading file %s\n", line);
for (auto i = 0; i < MAX_PATH; i++) {
if (line[i] == '\n') {
line[i] = 0;
}
}
const auto file = new uMod_File(line);
const auto result = file->GetContent();
if (file->Textures.size() > 0) {
if (!result) {
Message("MainLoop: WARNING! GetContent returned failure, but some textures have been loaded for %s\n", line);
}
Message("MainLoop: Texture count %d %s\n", file->Textures.size(), line);
for (auto& texture : file->Textures) {
AddFile(texture.data.data(), texture.data.size(), texture.hash, true);
}
PropagateUpdate(nullptr);
}
else {
Message("MainLoop: Failed to load any textures for %s\n", line);
}
}
}
}
int uMod_TextureServer::MainLoop() // run as a separated thread
{
Message("MainLoop: searching for modlist.txt\n");
char gwpath[MAX_PATH];
GetModuleFileName(GetModuleHandle(nullptr), gwpath, MAX_PATH); //ask for name and path of this executable
char* last_backslash = strrchr(gwpath, '\\');
if (last_backslash != nullptr) {
// Terminate the string at the last backslash to remove the executable name
*last_backslash = '\0';
}
strcat(gwpath, "\\modlist.txt");
LoadModsFromFile(gwpath);
char umodpath[MAX_PATH];
strcpy(umodpath, UModName);
last_backslash = strrchr(umodpath, '\\');
if (last_backslash != nullptr) {
// Terminate the string at the last backslash to remove the executable name
*last_backslash = '\0';
}
strcat(umodpath, "\\modlist.txt");
LoadModsFromFile(umodpath);
Message("MainLoop: begin\n");
for (auto i = 0; i < 10; i++) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return RETURN_OK;
}
+4163
View File
File diff suppressed because it is too large Load Diff
+3152
View File
File diff suppressed because it is too large Load Diff