mirror of
https://github.com/gwdevhub/gMod.git
synced 2026-07-26 00:45:31 +00:00
uMod 2 branch
This commit is contained in:
@@ -0,0 +1,859 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "uMod_Main.h"
|
||||
|
||||
|
||||
uMod_TextureClient::uMod_TextureClient(uMod_TextureServer* server, IDirect3DDevice9* device)
|
||||
{
|
||||
Message("uMod_TextureClient::uMod_TextureClient(void): %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 = NULL;
|
||||
|
||||
if (Server!=NULL)
|
||||
{
|
||||
if (Server->AddClient( this, &FileToMod, &NumberToMod))
|
||||
{
|
||||
Server=NULL;
|
||||
NumberToMod = 0;
|
||||
FileToMod = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i=0; i<NumberToMod; i++) {FileToMod[i].NumberOfTextures=0; FileToMod[i].Textures = NULL;}
|
||||
}
|
||||
}
|
||||
Mutex = CreateMutex(NULL, false, NULL);
|
||||
|
||||
Update = NULL;
|
||||
NumberOfUpdate = -1;
|
||||
Bool_CheckAgainNonAdded = false;
|
||||
FontColour = D3DCOLOR_ARGB(255,255,0,0);
|
||||
TextureColour = D3DCOLOR_ARGB(255,0,255,0);
|
||||
}
|
||||
|
||||
uMod_TextureClient::~uMod_TextureClient(void)
|
||||
{
|
||||
Message("uMod_TextureClient::~uMod_TextureClient(void): %lu\n", this);
|
||||
if (Server!=NULL) Server->RemoveClient(this);
|
||||
|
||||
if (Mutex!=NULL) CloseHandle(Mutex);
|
||||
|
||||
if (Update!=NULL) delete [] Update;
|
||||
if (FileToMod!=NULL)
|
||||
{
|
||||
for (int i=0; i<NumberToMod; i++) if (FileToMod[i].Textures!=NULL) delete [] FileToMod[i].Textures;
|
||||
delete [] FileToMod;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uMod_TextureClient::AddTexture( uMod_IDirect3DTexture9* pTexture)
|
||||
{
|
||||
void *cpy;
|
||||
long ret = D3D9Device->QueryInterface( IID_IDirect3DTexture9, &cpy);
|
||||
if (ret == 0x01000000L) ((uMod_IDirect3DDevice9*)D3D9Device)->SetLastCreatedTexture(NULL); //this texture must no be added twice
|
||||
else ((uMod_IDirect3DDevice9Ex*) D3D9Device)->SetLastCreatedTexture(NULL); //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 (int ret = pTexture->GetHash( hash))
|
||||
{
|
||||
Bool_CheckAgainNonAdded = true;
|
||||
NonAdded_OriginalTextures.Add( pTexture);
|
||||
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;
|
||||
long ret = D3D9Device->QueryInterface( IID_IDirect3DTexture9, &cpy);
|
||||
if (ret == 0x01000000L) ((uMod_IDirect3DDevice9*)D3D9Device)->SetLastCreatedVolumeTexture(NULL); //this texture must no be added twice
|
||||
else ((uMod_IDirect3DDevice9Ex*) D3D9Device)->SetLastCreatedVolumeTexture(NULL); //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 (int ret = pTexture->GetHash( hash))
|
||||
{
|
||||
Bool_CheckAgainNonAdded = true;
|
||||
NonAdded_OriginalVolumeTextures.Add( pTexture);
|
||||
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;
|
||||
long ret = D3D9Device->QueryInterface( IID_IDirect3DTexture9, &cpy);
|
||||
if (ret == 0x01000000L) ((uMod_IDirect3DDevice9*)D3D9Device)->SetLastCreatedCubeTexture(NULL); //this texture must no be added twice
|
||||
else ((uMod_IDirect3DDevice9Ex*) D3D9Device)->SetLastCreatedCubeTexture(NULL); //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 (int ret = pTexture->GetHash( hash))
|
||||
{
|
||||
Bool_CheckAgainNonAdded = true;
|
||||
NonAdded_OriginalCubeTextures.Add( pTexture);
|
||||
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::CheckAgainNonAdded(void)
|
||||
{
|
||||
Message("uMod_TextureClient::CheckAgainNonAdded( %u, %u, %u): %lu\n", NonAdded_OriginalTextures.GetNumber(),
|
||||
NonAdded_OriginalVolumeTextures.GetNumber(), NonAdded_OriginalCubeTextures.GetNumber(), this);
|
||||
|
||||
Bool_CheckAgainNonAdded = false;
|
||||
|
||||
int num = NonAdded_OriginalTextures.GetNumber();
|
||||
for (int i=num-1; i>=0; i--)
|
||||
{
|
||||
uMod_IDirect3DTexture9* pTexture = NonAdded_OriginalTextures[i];
|
||||
|
||||
MyTypeHash hash;
|
||||
if (pTexture->GetHash( hash) == 0)
|
||||
{
|
||||
NonAdded_OriginalTextures.Remove(pTexture);
|
||||
OriginalTextures.Add( pTexture); // add the texture to the list of original texture
|
||||
LookUpToMod(pTexture); // check if this texture should be modded
|
||||
}
|
||||
}
|
||||
|
||||
num = NonAdded_OriginalVolumeTextures.GetNumber();
|
||||
for (int i=num-1; i>=0; i--)
|
||||
{
|
||||
uMod_IDirect3DVolumeTexture9* pTexture = NonAdded_OriginalVolumeTextures[i];
|
||||
|
||||
MyTypeHash hash;
|
||||
if (pTexture->GetHash( hash) == 0)
|
||||
{
|
||||
NonAdded_OriginalVolumeTextures.Remove(pTexture);
|
||||
OriginalVolumeTextures.Add( pTexture); // add the texture to the list of original texture
|
||||
LookUpToMod(pTexture); // check if this texture should be modded
|
||||
}
|
||||
}
|
||||
|
||||
num = NonAdded_OriginalCubeTextures.GetNumber();
|
||||
for (int i=num-1; i>=0; i--)
|
||||
{
|
||||
uMod_IDirect3DCubeTexture9* pTexture = NonAdded_OriginalCubeTextures[i];
|
||||
|
||||
MyTypeHash hash;
|
||||
if (pTexture->GetHash( hash) == 0)
|
||||
{
|
||||
NonAdded_OriginalCubeTextures.Remove(pTexture);
|
||||
OriginalCubeTextures.Add( pTexture); // add the texture to the list of original texture
|
||||
LookUpToMod(pTexture); // check if this texture should be modded
|
||||
}
|
||||
}
|
||||
Message("uMod_TextureClient::CheckAgainNonAdded() END: %lu\n", this);
|
||||
return (RETURN_OK);
|
||||
}
|
||||
|
||||
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
|
||||
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] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (int ret = OriginalTextures.Remove( pTexture)) return (ret); // remove this texture form the original list
|
||||
return (NonAdded_OriginalTextures.Remove( pTexture)); // also try to remove this texture form the non_added 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
|
||||
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] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (int ret = OriginalVolumeTextures.Remove( pTexture)) return (ret); // remove this texture form the original list
|
||||
return (NonAdded_OriginalVolumeTextures.Remove( pTexture)); // also try to remove this texture form the non_added 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
|
||||
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] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (int ret = OriginalCubeTextures.Remove( pTexture)) return (ret); // remove this texture form the original list
|
||||
return (NonAdded_OriginalCubeTextures.Remove( pTexture)); // also try to remove this texture form the non_added 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;
|
||||
long ret = D3D9Device->QueryInterface( IID_IDirect3DTexture9, &cpy);
|
||||
if (ret == 0x01000000L) pTexture = ((uMod_IDirect3DDevice9*)D3D9Device)->GetSingleTexture(); //this texture must no be added twice
|
||||
else pTexture = ((uMod_IDirect3DDevice9Ex*) D3D9Device)->GetSingleTexture(); //this texture must no be added twice
|
||||
|
||||
if (pTexture!=NULL) 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);
|
||||
}
|
||||
else 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);
|
||||
}
|
||||
else GameName[i]=0;
|
||||
return (RETURN_OK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uMod_TextureClient::SaveTexture(uMod_IDirect3DTexture9* pTexture)
|
||||
{
|
||||
if (pTexture==NULL) 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, NULL)) return (RETURN_TEXTURE_NOT_SAVED);
|
||||
return (RETURN_OK);
|
||||
}
|
||||
|
||||
int uMod_TextureClient::SaveTexture(uMod_IDirect3DVolumeTexture9* pTexture)
|
||||
{
|
||||
if (pTexture==NULL) 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, NULL)) return (RETURN_TEXTURE_NOT_SAVED);
|
||||
return (RETURN_OK);
|
||||
}
|
||||
|
||||
int uMod_TextureClient::SaveTexture(uMod_IDirect3DCubeTexture9* pTexture)
|
||||
{
|
||||
if (pTexture==NULL) 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, NULL)) 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 (int ret = LockMutex()) {gl_ErrorState |= uMod_ERROR_TEXTURE; return (ret);}
|
||||
if (Update!=NULL) delete [] Update;
|
||||
Update = update;
|
||||
NumberOfUpdate = number;
|
||||
return (UnlockMutex());
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uMod_TextureClient::MergeUpdate(void)
|
||||
{
|
||||
if (NumberOfUpdate<0) {return (RETURN_OK);}
|
||||
if (int ret = LockMutex()) {gl_ErrorState |= uMod_ERROR_TEXTURE ; return (ret);}
|
||||
|
||||
Message("uMod_TextureClient::MergeUpdate(): %lu\n", this);
|
||||
|
||||
for (int i=0; i<NumberOfUpdate; i++) {Update[i].NumberOfTextures=0; Update[i].Textures = NULL;} // this is already done, but safety comes first ^^
|
||||
|
||||
int pos_old=0;
|
||||
int pos_new=0;
|
||||
int *to_lookup = NULL;
|
||||
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
|
||||
if (FileToMod[pos_old].Textures!=NULL) delete [] FileToMod[pos_old].Textures; // we delete the memory
|
||||
FileToMod[pos_old].NumberOfTextures = 0;
|
||||
FileToMod[pos_old].Textures = NULL;
|
||||
|
||||
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:
|
||||
{
|
||||
uMod_IDirect3DTexture9 *pTexture = (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:
|
||||
{
|
||||
uMod_IDirect3DVolumeTexture9 *pTexture = (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:
|
||||
{
|
||||
uMod_IDirect3DCubeTexture9 *pTexture = (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 = NULL;
|
||||
}
|
||||
// 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
|
||||
if (FileToMod[pos_old].Textures!=NULL) delete [] FileToMod[pos_old].Textures; // we delete the memory
|
||||
FileToMod[pos_old].Textures = NULL;
|
||||
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 (FileToMod!=NULL)
|
||||
{
|
||||
delete [] FileToMod;
|
||||
}
|
||||
|
||||
FileToMod = Update;
|
||||
NumberToMod = NumberOfUpdate;
|
||||
|
||||
NumberOfUpdate = -1;
|
||||
Update = NULL;
|
||||
|
||||
|
||||
if (num_to_lookup>0)
|
||||
{
|
||||
uMod_IDirect3DTexture9* single_texture;
|
||||
void *cpy;
|
||||
long ret = D3D9Device->QueryInterface( IID_IDirect3DTexture9, &cpy);
|
||||
if (ret == 0x01000000L) single_texture = ((uMod_IDirect3DDevice9*)D3D9Device)->GetSingleTexture(); //this texture must no be added twice
|
||||
else single_texture = ((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==NULL || 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 = ((uMod_IDirect3DDevice9*)D3D9Device)->GetSingleVolumeTexture(); //this texture must no be added twice
|
||||
else single_volume_texture = ((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==NULL || 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 = ((uMod_IDirect3DDevice9*)D3D9Device)->GetSingleCubeTexture(); //this texture must no be added twice
|
||||
else single_cube_texture = ((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==NULL || 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (to_lookup != NULL) delete [] to_lookup;
|
||||
|
||||
Message("uMod_TextureClient::MergeUpdate() END: %lu\n", this);
|
||||
|
||||
CheckAgainNonAdded();
|
||||
return (UnlockMutex());
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uMod_TextureClient::LockMutex(void)
|
||||
{
|
||||
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(void)
|
||||
{
|
||||
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==NULL || 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!=NULL) return (RETURN_OK); // bug, this texture is already switched
|
||||
int index = LookUpToMod( pTexture->Hash, num_index_list, index_list);
|
||||
if (index>=0)
|
||||
{
|
||||
uMod_IDirect3DTexture9 *fake_Texture;
|
||||
if (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
|
||||
{
|
||||
IDirect3DBaseTexture9 **temp = new IDirect3DBaseTexture9*[FileToMod[index].NumberOfTextures+1];
|
||||
for (int j=0; j<FileToMod[index].NumberOfTextures; j++) temp[j] = FileToMod[index].Textures[j];
|
||||
|
||||
if (FileToMod[index].Textures!=NULL) 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!=NULL) return (RETURN_OK); // bug, this texture is already switched
|
||||
int index = LookUpToMod( pTexture->Hash, num_index_list, index_list);
|
||||
if (index>=0)
|
||||
{
|
||||
uMod_IDirect3DVolumeTexture9 *fake_Texture;
|
||||
if (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
|
||||
{
|
||||
IDirect3DBaseTexture9 **temp = new IDirect3DBaseTexture9*[FileToMod[index].NumberOfTextures+1];
|
||||
for (int j=0; j<FileToMod[index].NumberOfTextures; j++) temp[j] = FileToMod[index].Textures[j];
|
||||
|
||||
if (FileToMod[index].Textures!=NULL) 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!=NULL) return (RETURN_OK); // bug, this texture is already switched
|
||||
int index = LookUpToMod( pTexture->Hash, num_index_list, index_list);
|
||||
if (index>=0)
|
||||
{
|
||||
uMod_IDirect3DCubeTexture9 *fake_Texture;
|
||||
if (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
|
||||
{
|
||||
IDirect3DBaseTexture9 **temp = new IDirect3DBaseTexture9*[FileToMod[index].NumberOfTextures+1];
|
||||
for (int j=0; j<FileToMod[index].NumberOfTextures; j++) temp[j] = FileToMod[index].Textures[j];
|
||||
|
||||
if (FileToMod[index].Textures!=NULL) 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, NULL, NULL, (IDirect3DTexture9 **) ppTexture))
|
||||
//if (D3D_OK != D3DXCreateTextureFromFileInMemory( D3D9Device, file_in_memory->pData, file_in_memory->Size, (IDirect3DTexture9 **) ppTexture))
|
||||
{
|
||||
*ppTexture=NULL;
|
||||
return (RETURN_TEXTURE_NOT_LOADED);
|
||||
}
|
||||
(*ppTexture)->FAKE = true;
|
||||
|
||||
void *cpy;
|
||||
long ret = D3D9Device->QueryInterface( IID_IDirect3DTexture9, &cpy);
|
||||
if (ret == 0x01000000L) ((uMod_IDirect3DDevice9*)D3D9Device)->SetLastCreatedTexture(NULL); //this texture must no be added twice
|
||||
else ((uMod_IDirect3DDevice9Ex*) D3D9Device)->SetLastCreatedTexture(NULL); //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, NULL, NULL, (IDirect3DVolumeTexture9 **) ppTexture))
|
||||
//if (D3D_OK != D3DXCreateVolumeTextureFromFileInMemory( D3D9Device, file_in_memory->pData, file_in_memory->Size, (IDirect3DVolumeTexture9 **) ppTexture))
|
||||
{
|
||||
*ppTexture=NULL;
|
||||
return (RETURN_TEXTURE_NOT_LOADED);
|
||||
}
|
||||
(*ppTexture)->FAKE = true;
|
||||
|
||||
void *cpy;
|
||||
long ret = D3D9Device->QueryInterface( IID_IDirect3DTexture9, &cpy);
|
||||
if (ret == 0x01000000L) ((uMod_IDirect3DDevice9*)D3D9Device)->SetLastCreatedVolumeTexture(NULL); //this texture must no be added twice
|
||||
else ((uMod_IDirect3DDevice9Ex*) D3D9Device)->SetLastCreatedVolumeTexture(NULL); //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, NULL, NULL, (IDirect3DCubeTexture9 **) ppTexture))
|
||||
//if (D3D_OK != D3DXCreateCubeTextureFromFileInMemory( D3D9Device, file_in_memory->pData, file_in_memory->Size, (IDirect3DCubeTexture9 **) ppTexture))
|
||||
{
|
||||
*ppTexture=NULL;
|
||||
return (RETURN_TEXTURE_NOT_LOADED);
|
||||
}
|
||||
(*ppTexture)->FAKE = true;
|
||||
|
||||
void *cpy;
|
||||
long ret = D3D9Device->QueryInterface( IID_IDirect3DTexture9, &cpy);
|
||||
if (ret == 0x01000000L) ((uMod_IDirect3DDevice9*)D3D9Device)->SetLastCreatedCubeTexture(NULL); //this texture must no be added twice
|
||||
else ((uMod_IDirect3DDevice9Ex*) D3D9Device)->SetLastCreatedCubeTexture(NULL); //this texture must no be added twice
|
||||
|
||||
Message("LoadTexture( Cube %lu, %#lX): DONE\n", *ppTexture, file_in_memory->Hash);
|
||||
return (RETURN_OK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef uMod_TEXTUREHANDLER_HPP
|
||||
#define uMod_TEXTUREHANDLER_HPP
|
||||
|
||||
#include <d3d9.h>
|
||||
#include <d3d10.h>
|
||||
#include "../uMod_GlobalDefines.h"
|
||||
#include "..\uMod_Error.h"
|
||||
|
||||
|
||||
class uMod_TextureServer;
|
||||
|
||||
/*
|
||||
* An object of this class is owned by each d3dXX device.
|
||||
* functions called by the Server are called from the server thread instance.
|
||||
* All other functions are called from the render thread instance of the game itself.
|
||||
*/
|
||||
|
||||
class uMod_TextureClient
|
||||
{
|
||||
public:
|
||||
uMod_TextureClient(uMod_TextureServer* server);
|
||||
~uMod_TextureClient(void);
|
||||
|
||||
/**
|
||||
* Enable/Disable the "save all texture" mode. (called from the server)
|
||||
* @param val
|
||||
* @return RETURN_OK on success
|
||||
*/
|
||||
int SaveAllTextures(bool val);
|
||||
|
||||
/**
|
||||
* Enable/Disable the "save all texture" mode. (called from the server)
|
||||
* @param val
|
||||
* @return RETURN_OK on success
|
||||
*/
|
||||
int SaveSingleTexture(bool val);
|
||||
|
||||
/**
|
||||
* Set the directory, wher the texture should be stored (called from the server)
|
||||
* @param dir
|
||||
* @return RETURN_OK on success
|
||||
*/
|
||||
int SetSaveDirectory( wchar_t *dir);
|
||||
|
||||
/**
|
||||
* Set the name of the game (default name of executabel without the extension .exe) (called from the server)
|
||||
* @param name
|
||||
* @return RETURN_OK on success
|
||||
*/
|
||||
int SetGameName( wchar_t *name);
|
||||
|
||||
/**
|
||||
* Set the key to got to the previous texture (called from the server)
|
||||
* @param key
|
||||
* @return RETURN_OK
|
||||
*/
|
||||
int SetKeyBack( int key) {if (key>0) KeyBack = key; return (RETURN_OK);}
|
||||
/**
|
||||
* Set the key for saving the texture (called from the server)
|
||||
* @param key
|
||||
* @return RETURN_OK
|
||||
*/
|
||||
int SetKeySave( int key) {if (key>0) KeySave = key; return (RETURN_OK);}
|
||||
/**
|
||||
* Set the key to go to the next texture (called from the server)
|
||||
* @param key
|
||||
* @return RETURN_OK
|
||||
*/
|
||||
int SetKeyNext( int key) {if (key>0) KeyNext = key; return (RETURN_OK);}
|
||||
|
||||
/**
|
||||
* Set the font color "during save single" texture mode. (called from the server)
|
||||
* @param r red value (0..255)
|
||||
* @param g green value (0..255)
|
||||
* @param b blue value (0..255)
|
||||
* @return
|
||||
*/
|
||||
int SetFontColour( DWORD r, DWORD g, DWORD b) {FontColour = D3DCOLOR_ARGB(255, r,g,b); return (RETURN_OK);}
|
||||
/**
|
||||
* Set the texture color "during save single" texture mode. (called from the server)
|
||||
* @param r red value (0..255)
|
||||
* @param g green value (0..255)
|
||||
* @param b blue value (0..255)
|
||||
* @return RETURN_OK
|
||||
*/
|
||||
int SetTextureColour( DWORD r, DWORD g, DWORD b) {TextureColour = D3DCOLOR_ARGB(255, r,g,b); return (RETURN_OK);}
|
||||
|
||||
|
||||
/**
|
||||
* The server add an update to the client.(called from server)
|
||||
* @param update Pointer to an array of TextureFileStruct, the client \b must delete this array!
|
||||
* @param number number of entries
|
||||
* @return RETURN_OK on success
|
||||
*/
|
||||
int AddUpdate(TextureFileStruct* update, int number);
|
||||
/**
|
||||
* Merge the latest update (called from client -> e.g. uMod_IDirect3DDevice9::BeginScene())
|
||||
* @return RETURN_OK on success
|
||||
*/
|
||||
int MergeUpdate(void);
|
||||
|
||||
|
||||
bool BoolSaveAllTextures; //< true if all textures should be saved
|
||||
bool BoolSaveSingleTexture; //< true if "save single texture" mode is enabled
|
||||
int KeyBack; //< key value for going to the previous texture
|
||||
int KeySave; //< key value for saving the current texture
|
||||
int KeyNext; //< key value for going to the next texture
|
||||
|
||||
D3DCOLOR FontColour; //< color of the message ("save single texture" mode)
|
||||
D3DCOLOR TextureColour; //< color of the texture ("save single texture" mode)
|
||||
|
||||
private:
|
||||
uMod_TextureServer* Server; //< Pointer to the server
|
||||
wchar_t SavePath[MAX_PATH]; //< saving directory
|
||||
wchar_t GameName[MAX_PATH]; //< game name
|
||||
|
||||
TextureFileStruct* Update; //< array which stores the file in memory and the hash of each texture to be modded
|
||||
int NumberOfUpdate; //< number of texture to be modded
|
||||
|
||||
/**
|
||||
* Lock the mutex. The mutex protect the AddUpdate and MergeUpdate function to be called simultaneously.
|
||||
* @return RETURN_OK on success
|
||||
*/
|
||||
int LockMutex();
|
||||
/**
|
||||
* Unloock the mutex. The mutex protect the AddUpdate and MergeUpdate function to be called simultaneously.
|
||||
* @return RETURN_OK on success
|
||||
*/
|
||||
int UnlockMutex();
|
||||
HANDLE Mutex; //< The mutex protect the AddUpdate and MergeUpdate function to be called simultaneously.
|
||||
|
||||
int NumberToMod; //< number of texture to be modded
|
||||
TextureFileStruct* FileToMod; //< array which stores the file in memory and the hash of each texture to be modded
|
||||
|
||||
|
||||
int LookUpToMod( MyTypeHash hash, int num_index_list, int *index_list); // called from LookUpToMod(...);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* uMod_TEXTUREHANDLER_HPP_ */
|
||||
@@ -0,0 +1,828 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#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;
|
||||
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]==L'\\' || game[len]==L'/') path_pos=len+1;
|
||||
else if (game[len]==L'.') 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;
|
||||
|
||||
KeyBack = 0;
|
||||
KeySave = 0;
|
||||
KeyNext = 0;
|
||||
|
||||
FontColour = 0u;
|
||||
TextureColour = 0u;
|
||||
|
||||
Pipe.In = INVALID_HANDLE_VALUE;
|
||||
Pipe.Out = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
uMod_TextureServer::~uMod_TextureServer(void)
|
||||
{
|
||||
Message("~uMod_TextureServer(void): %lu\n", this);
|
||||
if (Mutex != NULL) 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 (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)
|
||||
{
|
||||
DWORD r = (FontColour>>16)&0xFF;
|
||||
DWORD g = (FontColour>>8)&0xFF;
|
||||
DWORD b = (FontColour)&0xFF;
|
||||
client->SetFontColour( r, g, b);
|
||||
}
|
||||
if (TextureColour>0u)
|
||||
{
|
||||
DWORD r = (TextureColour>>16)&0xFF;
|
||||
DWORD g = (TextureColour>>8)&0xFF;
|
||||
DWORD b = (TextureColour)&0xFF;
|
||||
client->SetTextureColour( r, g, b);
|
||||
}
|
||||
|
||||
|
||||
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; i<LenghtOfClients; i++) temp[i] = Clients[i];
|
||||
if (Clients!=NULL) 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): %lu\n", client);
|
||||
if (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 = NULL;
|
||||
|
||||
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
|
||||
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; i<num; i++) if (OldMod[i]->Hash == 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;
|
||||
|
||||
/*
|
||||
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 = NULL;
|
||||
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
|
||||
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(MyTypeHash 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::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(DWORD colour) // called from Mainloop()
|
||||
{
|
||||
if (colour==0u) return (RETURN_OK);
|
||||
if (int ret = LockMutex())
|
||||
{
|
||||
gl_ErrorState |= uMod_ERROR_SERVER;
|
||||
return (ret);
|
||||
}
|
||||
FontColour = colour;
|
||||
DWORD r = (FontColour>>16)&0xFF;
|
||||
DWORD g = (FontColour>>8)&0xFF;
|
||||
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 (int ret = LockMutex())
|
||||
{
|
||||
gl_ErrorState |= uMod_ERROR_SERVER;
|
||||
return (ret);
|
||||
}
|
||||
TextureColour = colour;
|
||||
DWORD r = (TextureColour>>16)&0xFF;
|
||||
DWORD g = (TextureColour>>8)&0xFF;
|
||||
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 (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; i<NumberOfClients; i++)
|
||||
{
|
||||
TextureFileStruct* update;
|
||||
int number;
|
||||
if (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 )
|
||||
{
|
||||
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; 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(void)
|
||||
{
|
||||
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(void)
|
||||
{
|
||||
if (ReleaseMutex( Mutex) == 0) return (RETURN_MUTEX_UNLOCK);
|
||||
return (RETURN_OK);
|
||||
}
|
||||
|
||||
int uMod_TextureServer::MainLoop(void) // run as a separated thread
|
||||
{
|
||||
Message("MainLoop: begin\n");
|
||||
if (Pipe.In == INVALID_HANDLE_VALUE) return (RETURN_PIPE_NOT_OPENED);
|
||||
char *buffer;
|
||||
try {buffer = new char[BIG_BUFSIZE];}
|
||||
catch (...) {return (RETURN_NO_MEMORY);}
|
||||
|
||||
unsigned long num = 0u;
|
||||
bool update_textures = false;
|
||||
|
||||
unsigned int texture_size = 0u;
|
||||
unsigned int texture_received = 0u;
|
||||
char *texture_data = (char*)0;
|
||||
bool texture_force = false;
|
||||
MyTypeHash texture_hash = 0u;
|
||||
|
||||
Message("MainLoop: started\n");
|
||||
while (1)
|
||||
{
|
||||
Message("MainLoop: run\n");
|
||||
bool ret = ReadFile(Pipe.In, // pipe handle
|
||||
buffer, // buffer to receive reply
|
||||
BIG_BUFSIZE, // size of buffer
|
||||
&num, // number of bytes read
|
||||
NULL); // not overlapped
|
||||
|
||||
Message("MainLoop: read something (%lu)\n", num);
|
||||
if (ret || GetLastError() == ERROR_MORE_DATA)
|
||||
{
|
||||
unsigned int pos = 0;
|
||||
MsgStruct *commands;
|
||||
unsigned int size=0u;
|
||||
while (pos < num)
|
||||
{
|
||||
if (texture_received<texture_size)
|
||||
{
|
||||
while (pos<num && texture_received<texture_size) texture_data[texture_received++] = buffer[pos++];
|
||||
if (texture_received==texture_size)
|
||||
{
|
||||
AddFile( texture_data, texture_size, texture_hash, texture_force);
|
||||
texture_data = (char*)0;
|
||||
texture_size = 0u;
|
||||
texture_received = 0u;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
commands = (MsgStruct*) &buffer[pos];
|
||||
|
||||
switch (commands->Control)
|
||||
{
|
||||
case CONTROL_END_TEXTURES:
|
||||
{
|
||||
Message("MainLoop: CONTROL_END_TEXTURES (): %lu\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[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 (%#lX %u, %u): %lu\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[texture_size];
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
texture_size = 0u;
|
||||
texture_data = (char*)0;
|
||||
gl_ErrorState |= uMod_ERROR_MEMORY | uMod_ERROR_SERVER;
|
||||
}
|
||||
Message("MainLoop: CONTROL_ADD_TEXTURE_DATA (%#lX %u, %u): %lu\n", texture_hash, texture_size, texture_data, this);
|
||||
break;
|
||||
}
|
||||
case CONTROL_REMOVE_TEXTURE:
|
||||
{
|
||||
Message("MainLoop: CONTROL_REMOVE_TEXTURE (%#lX): %lu\n", commands->Hash, this);
|
||||
RemoveFile(commands->Hash);
|
||||
//update_textures = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case CONTROL_SAVE_SINGLE:
|
||||
{
|
||||
Message("MainLoop: CONTROL_SAVE_SINGLE (%d): %lu\n", commands->Value, this);
|
||||
if (commands->Value == 0) SaveSingleTexture(false);
|
||||
else SaveSingleTexture(true);
|
||||
break;
|
||||
}
|
||||
case CONTROL_SAVE_ALL:
|
||||
{
|
||||
Message("MainLoop: CONTROL_SAVE_ALL (%d): %lu\n", commands->Value, this);
|
||||
if (commands->Value == 0) SaveAllTextures(false);
|
||||
else SaveAllTextures(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 (%#X): %lu\n", commands->Value, this);
|
||||
SetKeyBack(commands->Value);
|
||||
break;
|
||||
}
|
||||
case CONTROL_KEY_SAVE:
|
||||
{
|
||||
Message("MainLoop: CONTROL_KEY_SAVE (%#X): %lu\n", commands->Value, this);
|
||||
SetKeySave(commands->Value);
|
||||
break;
|
||||
}
|
||||
case CONTROL_KEY_NEXT:
|
||||
{
|
||||
Message("MainLoop: CONTROL_KEY_NEXT (%#X): %lu\n", commands->Value, this);
|
||||
SetKeyNext(commands->Value);
|
||||
break;
|
||||
}
|
||||
case CONTROL_FONT_COLOUR:
|
||||
{
|
||||
Message("MainLoop: CONTROL_FONT_COLOUR (%#X): %lu\n", commands->Value, this);
|
||||
SetFontColour(commands->Value);
|
||||
break;
|
||||
}
|
||||
case CONTROL_TEXTURE_COLOUR:
|
||||
{
|
||||
Message("MainLoop: CONTROL_TEXTURE_COLOUR (%#X): %lu\n", commands->Value, this);
|
||||
SetTextureColour(commands->Value);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Message("MainLoop: DEFAULT: %lu %lu %#lX\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) // 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
|
||||
WriteFile(Pipe.Out, (const void*) game, len * sizeof(wchar_t), &num, NULL);
|
||||
|
||||
// now we can open the pipe for reading
|
||||
Message("OpenPipe: In\n");
|
||||
Pipe.In = CreateFileW(PIPE_uMod2Game, // pipe name
|
||||
GENERIC_READ, // read access
|
||||
0, // no sharing
|
||||
NULL, // default security attributes
|
||||
OPEN_EXISTING, // opens existing pipe
|
||||
0, // default attributes
|
||||
NULL); // no template file
|
||||
|
||||
if (Pipe.In == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(Pipe.In);
|
||||
Pipe.In = INVALID_HANDLE_VALUE;
|
||||
return (RETURN_PIPE_NOT_OPENED);
|
||||
}
|
||||
|
||||
Message("OpenPipe: Done\n");
|
||||
return (RETURN_OK);
|
||||
}
|
||||
|
||||
int uMod_TextureServer::ClosePipe(void) //called from ExitInstance, this must be done, otherwise the Mainloop will wait endless on the ReadFile()
|
||||
{
|
||||
Message("ClosePipe:\n");
|
||||
|
||||
// We close the outgoing pipe first.
|
||||
// The GUI will notice that the opposite side of it incoming pipe is closed
|
||||
// and closes it outgoing (our incoming) pipe and thus cancel the ReadFile() in the Mainloop()
|
||||
|
||||
if (Pipe.Out != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DisconnectNamedPipe(Pipe.Out);
|
||||
CloseHandle(Pipe.Out);
|
||||
Pipe.Out = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (Pipe.In != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DisconnectNamedPipe(Pipe.In);
|
||||
CloseHandle(Pipe.In);
|
||||
Pipe.In = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
return (RETURN_OK);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef uMod_TEXTURESERVER_H_
|
||||
#define uMod_TEXTURESERVER_H_
|
||||
|
||||
#include "../uMod_GlobalDefines.h"
|
||||
#include "uMod_ArrayHandler.h"
|
||||
|
||||
|
||||
/*
|
||||
* An object of this class is created only once.
|
||||
* The Mainloop functions is executed by a server thread,
|
||||
* which listen on a pipe.
|
||||
*
|
||||
* Functions called by the Client are called from the a thread instance of the game itself.
|
||||
* Nearly all other functions are called from the server thread instance.
|
||||
*/
|
||||
|
||||
|
||||
class uMod_TextureClient;
|
||||
|
||||
class uMod_TextureServer
|
||||
{
|
||||
public:
|
||||
uMod_TextureServer(wchar_t *name);
|
||||
~uMod_TextureServer(void);
|
||||
|
||||
int AddClient(uMod_TextureClient *client, TextureFileStruct** update, int* number); // called from a Client
|
||||
int RemoveClient(uMod_TextureClient *client); // called from a Client
|
||||
|
||||
int OpenPipe(wchar_t *name); // called on initialization of our d3d9 fake dll
|
||||
int ClosePipe(void); // called on exit of our d3d9 fake dll
|
||||
int MainLoop(void); // is executed in a server thread
|
||||
|
||||
|
||||
// following functions are only public for testing purpose !!
|
||||
// they should be private and only be called from the Mainloop
|
||||
|
||||
int AddFile( char* buffer, unsigned int size, MyTypeHash hash, bool force); // called from Mainloop(), if the content of the texture is sent
|
||||
int AddFile( wchar_t* file_name, MyTypeHash hash, bool force); // called from Mainloop(), if the name and the path to the file is sent
|
||||
int RemoveFile( MyTypeHash hash); // called from Mainloop()
|
||||
|
||||
int SaveAllTextures(bool val); // called from Mainloop()
|
||||
int SaveSingleTexture(bool val); // called from Mainloop()
|
||||
|
||||
int SetSaveDirectory( wchar_t *dir); // called from Mainloop()
|
||||
|
||||
|
||||
int SetKeyBack( int key); // called from Mainloop()
|
||||
int SetKeySave( int key); // called from Mainloop()
|
||||
int SetKeyNext( int key); // called from Mainloop()
|
||||
|
||||
int SetFontColour(DWORD colour); // called from Mainloop()
|
||||
int SetTextureColour(DWORD colour); // called from Mainloop()
|
||||
|
||||
private:
|
||||
bool BoolSaveAllTextures;
|
||||
bool BoolSaveSingleTexture;
|
||||
wchar_t SavePath[MAX_PATH];
|
||||
wchar_t GameName[MAX_PATH];
|
||||
|
||||
int PropagateUpdate(uMod_TextureClient* client=NULL); // called from Mainloop() if texture are loaded or removed
|
||||
int PrepareUpdate(TextureFileStruct** update, int* number); // called from PropagateUpdate() and AddClient()
|
||||
// generate a copy of the current texture to be modded
|
||||
// the file content of the textures are not copied, the clients get the pointer to the file content
|
||||
// but the arrays allocate by this function, must be deleted by the client
|
||||
|
||||
int LockMutex();
|
||||
int UnlockMutex();
|
||||
HANDLE Mutex;
|
||||
|
||||
|
||||
int KeyBack;
|
||||
int KeySave;
|
||||
int KeyNext;
|
||||
|
||||
DWORD FontColour;
|
||||
DWORD TextureColour;
|
||||
|
||||
|
||||
PipeStruct Pipe;
|
||||
|
||||
uMod_TextureClient** Clients;
|
||||
int NumberOfClients;
|
||||
int LenghtOfClients;
|
||||
|
||||
uMod_FileHandler CurrentMod; // hold the file content of texture
|
||||
uMod_FileHandler OldMod; // hold the file content of texture which were added previously but are not needed any more
|
||||
// this is needed, because a texture clients might not have merged the last update and thus hold pointers to the file content of old textures
|
||||
};
|
||||
|
||||
|
||||
#endif /* uMod_TEXTURESERVER_H_ */
|
||||
Reference in New Issue
Block a user