/* This file is part of Universal Modding Engine. Universal Modding Engine is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Universal Modding Engine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Universal Modding Engine. If not, see . */ #include "uMod_Main.h" uMod_TextureServer::uMod_TextureServer(wchar_t *game) { Message("uMod_TextureServer(void): %lu\n", this); Mutex = CreateMutex(NULL, false, NULL); Clients = NULL; NumberOfClients = 0; LenghtOfClients = 0; BoolSaveAllTextures = false; BoolSaveSingleTexture = false; BoolShowTextureString = false; BoolSupportTPF = false; SavePath[0] = 0; int len=0; int path_pos=0; int dot_pos=0; for (len=0; lenpath_pos) len = dot_pos - path_pos; else len -= path_pos; for (int i=0; ipData; //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, const int version) // called from a client { Message("AddClient(%lu): %lu\n", client, this); if (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->ShowTextureString(BoolShowTextureString); client->SupportTPF(BoolSupportTPF); client->SetSaveDirectory(SavePath); client->SetKeyBack(KeyBack); client->SetKeySave(KeySave); client->SetKeyNext(KeyNext); client->SetFontColour( FontColour); client->SetTextureColour( TextureColour); client->SetWidthFilter( WidthFilter); client->SetHeightFilter( HeightFilter); client->SetDepthFilter( DepthFilter); client->SetFormatFilter(FormatFilter); client->SetFileFormat(FileFormat); if (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 = NULL; try {temp = new uMod_TextureClient*[LenghtOfClients + 10];} catch (...) { gl_ErrorState |= uMod_ERROR_MEMORY | uMod_ERROR_SERVER; if (int ret = UnlockMutex()) return (ret); return (RETURN_NO_MEMORY); } for (int i=0; iHash == hash) //look through all current textures { if (force) {temp = CurrentMod[i]; break;} // we need to reload it else { if (buffer!=NULL) delete [] buffer; return (RETURN_OK); // we still have added this texture } } if (temp==NULL) // if not found, look through all old textures { num = OldMod.GetNumber(); for (int i=0; iHash == hash) { temp = OldMod[i]; OldMod.Remove(temp); CurrentMod.Add(temp); if (force) break; // we must reload it else { if (buffer!=NULL) delete [] buffer; return (RETURN_OK); // we should not reload it } } } bool new_file = true; if (temp!=NULL) //if it was found, we delete the old file content { new_file = false; if (temp->pData!=NULL) delete [] temp->pData; temp->pData = NULL; } else //if it was not found, we need to create a new object { new_file = true; temp = new TextureFileStruct; temp->Reference = -1; } temp->pData = buffer; for (unsigned int i=0; ipData[i] = buffer[i]; temp->Size = (unsigned int) size; temp->NumberOfTextures = 0; temp->Textures = NULL; temp->Hash = hash; //if (new_file) temp->ForceReload = false; // no need to force a load of the texture //else temp->ForceReload = force; Message("uMod_TextureServer::End AddFile(%#lX)\n", hash); if (new_file) return (CurrentMod.Add(temp)); // new files must be added to the list of the CurrentMod else 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 = NULL; int num = CurrentMod.GetNumber(); for (int i = 0; i < num; i++) if (CurrentMod[i]->Hash == hash) { if (force) {temp = CurrentMod[i]; break;} else return (RETURN_OK); } if (temp==NULL) { 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; else 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); unsigned int size = ftell(file); fseek (file, 0, SEEK_SET); bool new_file = true; if (temp!=NULL) { new_file = false; if (temp->pData!=NULL) delete [] temp->pData; temp->pData = NULL; } 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); } 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 = NULL; 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)); else return (RETURN_OK); } */ int uMod_TextureServer::RemoveFile(DWORD64 hash) // called from Mainloop() { Message("RemoveFile( %lu): %lu\n", hash, this); 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 (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 (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::ShowTextureString(bool val) // called from Mainloop() { if (BoolShowTextureString == val) return (RETURN_OK); BoolShowTextureString = val; if (int ret = LockMutex()) { gl_ErrorState |= uMod_ERROR_SERVER; return (ret); } for (int i = 0; i < NumberOfClients; i++) { Clients[i]->ShowTextureString(BoolShowTextureString); } return (UnlockMutex()); } int uMod_TextureServer::SupportTPF(bool val) // called from Mainloop() { if (BoolSupportTPF == val) return (RETURN_OK); BoolSupportTPF = val; if (int ret = LockMutex()) { gl_ErrorState |= uMod_ERROR_SERVER; return (ret); } for (int i = 0; i < NumberOfClients; i++) { Clients[i]->SupportTPF(BoolSupportTPF); } 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); } else SavePath[i] = 0; if (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 (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 (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 (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(DWORD64 colour) // called from Mainloop() { if (colour==0u) return (RETURN_OK); if (int ret = LockMutex()) { gl_ErrorState |= uMod_ERROR_SERVER; return (ret); } FontColour = colour; Message("uMod_TextureServer::SetFontColour( %#lX): %lu\n",colour, this); for (int i = 0; i < NumberOfClients; i++) { Clients[i]->SetFontColour( colour); } return (UnlockMutex()); } int uMod_TextureServer::SetTextureColour(DWORD64 colour) // called from Mainloop() { if (colour==0u) return (RETURN_OK); if (int ret = LockMutex()) { gl_ErrorState |= uMod_ERROR_SERVER; return (ret); } TextureColour = colour; Message("uMod_TextureServer::SetTextureColour( %#lX): %lu\n", colour, this); for (int i = 0; i < NumberOfClients; i++) { Clients[i]->SetTextureColour( colour); } return (UnlockMutex()); } int uMod_TextureServer::SetFileFormat(DWORD64 format) // called from Mainloop() { if (int ret = LockMutex()) { gl_ErrorState |= uMod_ERROR_SERVER; return (ret); } FileFormat = format; Message("uMod_TextureServer::SetFileFormat( %lu): %lu\n", format, this); for (int i = 0; i < NumberOfClients; i++) { Clients[i]->SetFileFormat( format); } return (UnlockMutex()); } int uMod_TextureServer::SetFormatFilter(DWORD64 format) // called from Mainloop() { if (int ret = LockMutex()) { gl_ErrorState |= uMod_ERROR_SERVER; return (ret); } FormatFilter = format; Message("uMod_TextureServer::SetFormatFilter( %lu): %lu\n", format, this); for (int i = 0; i < NumberOfClients; i++) { Clients[i]->SetFormatFilter( format); } return (UnlockMutex()); } int uMod_TextureServer::SetWidthFilter(DWORD64 size) // called from Mainloop() { if (int ret = LockMutex()) { gl_ErrorState |= uMod_ERROR_SERVER; return (ret); } WidthFilter = size; Message("uMod_TextureServer::SetWidthFilter( %lu): %lu\n", size, this); for (int i = 0; i < NumberOfClients; i++) { Clients[i]->SetWidthFilter( size); } return (UnlockMutex()); } int uMod_TextureServer::SetHeightFilter(DWORD64 size) // called from Mainloop() { if (int ret = LockMutex()) { gl_ErrorState |= uMod_ERROR_SERVER; return (ret); } HeightFilter = size; Message("uMod_TextureServer::SetHeightFilter( %lu): %lu\n", size, this); for (int i = 0; i < NumberOfClients; i++) { Clients[i]->SetHeightFilter( size); } return (UnlockMutex()); } int uMod_TextureServer::SetDepthFilter(DWORD64 size) // called from Mainloop() { if (int ret = LockMutex()) { gl_ErrorState |= uMod_ERROR_SERVER; return (ret); } DepthFilter = size; Message("uMod_TextureServer::SetDepthFilter( %lu): %lu\n", size, this); for (int i = 0; i < NumberOfClients; i++) { Clients[i]->SetDepthFilter( size); } 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 (int ret = LockMutex()) { gl_ErrorState |= uMod_ERROR_TEXTURE; return (ret); } if (client != NULL) { TextureFileStruct* update; int number; if (int ret = PrepareUpdate( update, number)) return (ret); client->AddUpdate(update, number); } else { for (int i=0; iAddUpdate(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 ) { TextureFileStruct *tex1 = (TextureFileStruct*)elem1; TextureFileStruct *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 = NULL; 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; iControl) { case CONTROL_END_TEXTURES: { Message("MainLoop: CONTROL_END_TEXTURES (): %p\n", this); update_textures=true; break; } /* case CONTROL_FORCE_RELOAD_TEXTURE: force=true; case CONTROL_ADD_TEXTURE: { size = commands->Value; Message("MainLoop: CONTROL_ADD_TEXTURE (%#lX %u, %u %u): %lu\n", commands->Hash, size, sizeof(MsgStruct), sizeof(char), this); if (pos + sizeof(MsgStruct) + size <= num) AddFile( (wchar_t*) &buffer[pos + sizeof(MsgStruct)], commands->Hash, force); //update_textures = true; force = false; break; } */ case CONTROL_FORCE_RELOAD_TEXTURE_DATA: { texture_size = commands->Value; texture_received = 0u; texture_hash = commands->Hash; texture_force=true; try { texture_data = new char[(unsigned int) texture_size]; } catch (...) { texture_size = 0u; texture_data = (char*)0; gl_ErrorState |= uMod_ERROR_MEMORY | uMod_ERROR_SERVER; } Message("MainLoop: CONTROL_FORCE_RELOAD_TEXTURE_DATA (%#llX %llu, %p): %p\n", texture_hash, texture_size, texture_data, this); break; } case CONTROL_ADD_TEXTURE_DATA: { texture_size = commands->Value; texture_received = 0u; texture_hash = commands->Hash; texture_force=true; try { texture_data = new char[(unsigned int) texture_size]; } catch (...) { texture_size = 0u; texture_data = (char*)0; gl_ErrorState |= uMod_ERROR_MEMORY | uMod_ERROR_SERVER; } Message("MainLoop: CONTROL_ADD_TEXTURE_DATA (%#llX %llu, %p): %p\n", texture_hash, texture_size, texture_data, this); break; } case CONTROL_REMOVE_TEXTURE: { Message("MainLoop: CONTROL_REMOVE_TEXTURE (%#llX): %p\n", commands->Hash, this); RemoveFile(commands->Hash); //update_textures = true; break; } case CONTROL_SAVE_ALL: { Message("MainLoop: CONTROL_SAVE_ALL (%#llX): %p\n", commands->Value, this); if (commands->Value == 0) SaveAllTextures(false); else SaveAllTextures(true); break; } case CONTROL_SAVE_SINGLE: { Message("MainLoop: CONTROL_SAVE_SINGLE (%#llX): %p\n", commands->Value, this); if (commands->Value == 0) SaveSingleTexture(false); else SaveSingleTexture(true); break; } case CONTROL_SHOW_STRING: { Message("MainLoop: CONTROL_SHOW_STRING (%#llX): %p\n", commands->Value, this); if (commands->Value == 0) ShowTextureString(false); else ShowTextureString(true); break; } case CONTROL_SUPPORT_TPF: { Message("MainLoop: CONTROL_SUPPORT_TPF (%#llX): %p\n", commands->Value, this); if (commands->Value == 0) SupportTPF(false); else SupportTPF(true); break; } case CONTROL_SET_DIR: { size = commands->Value; if (pos + sizeof(MsgStruct) +size <= num) SetSaveDirectory( (wchar_t*) &buffer[pos + sizeof(MsgStruct)]); break; } case CONTROL_KEY_BACK: { Message("MainLoop: CONTROL_KEY_BACK (%#llX): %p\n", commands->Value, this); SetKeyBack((int) commands->Value); break; } case CONTROL_KEY_SAVE: { Message("MainLoop: CONTROL_KEY_SAVE (%#llX): %p\n", commands->Value, this); SetKeySave((int) commands->Value); break; } case CONTROL_KEY_NEXT: { Message("MainLoop: CONTROL_KEY_NEXT (%#llX): %p\n", commands->Value, this); SetKeyNext((int) commands->Value); break; } case CONTROL_FONT_COLOUR: { Message("MainLoop: CONTROL_FONT_COLOUR (%#llX): %p\n", commands->Value, this); SetFontColour(commands->Value); break; } case CONTROL_TEXTURE_COLOUR: { Message("MainLoop: CONTROL_TEXTURE_COLOUR (%#llX): %p\n", commands->Value, this); SetTextureColour(commands->Value); break; } case CONTROL_WIDTH_FILTER: { Message("MainLoop: CONTROL_WIDTH_FILTER (%#llX): %p\n", commands->Value, this); SetWidthFilter(commands->Value); break; } case CONTROL_HEIGHT_FILTER: { Message("MainLoop: CONTROL_HEIGHT_FILTER (%#llX): %p\n", commands->Value, this); SetHeightFilter(commands->Value); break; } case CONTROL_DEPTH_FILTER: { Message("MainLoop: CONTROL_DEPTH_FILTER (%#llX): %p\n", commands->Value, this); SetDepthFilter(commands->Value); break; } case CONTROL_FORMAT_FILTER: { Message("MainLoop: CONTROL_FORMAT_FILTER (%#llX): %p\n", commands->Value, this); SetFormatFilter(commands->Value); break; } case CONTROL_SAVE_FORMAT: { Message("MainLoop: CONTROL_SAVE_FORMAT (%#llX): %p\n", commands->Value, this); SetFileFormat(commands->Value); break; } default: { Message("MainLoop: DEFAULT: %lu %#llX %#llX\n", commands->Control, commands->Value, commands->Hash, this); break; } } pos += sizeof(MsgStruct) + size; } } if (update_textures) {PropagateUpdate(); update_textures=false;} } else { Message("MainLoop: error in ReadFile()\n"); delete [] buffer; ClosePipe(); return (RETURN_OK); } } delete [] buffer; return (RETURN_OK); } int uMod_TextureServer::OpenPipe(wchar_t *game, int injection_method) // called from InitInstance() { Message("OpenPipe: Out\n") // open first outgoing pipe !! Pipe.Out = CreateFileW(PIPE_Game2uMod, // pipe name GENERIC_WRITE, // write access 0, // no sharing NULL, // default security attributes OPEN_EXISTING, // opens existing pipe 0, // default attributes NULL); // no template file // Exit if an error other than ERROR_PIPE_BUSY occurs. if (Pipe.Out == INVALID_HANDLE_VALUE) return (RETURN_PIPE_NOT_OPENED); unsigned int len = 0u; while (game[len]) len++; len++; //to send also the zero unsigned long num; //send name of this game to uMod_GUI char *buffer=(char*)0; GetMemory(buffer, sizeof(int) + len * sizeof(wchar_t)); *((int*) buffer) = injection_method; char *p_game = (char*) game; for (unsigned int i=0; i