|
|
|
/*
|
|
|
|
custom.c - customization routines
|
|
|
|
Copyright (C) 2018 Uncle Mike
|
|
|
|
|
|
|
|
This program 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.
|
|
|
|
|
|
|
|
This program 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
#include "custom.h"
|
|
|
|
#include "ref_common.h"
|
|
|
|
|
|
|
|
static rgbdata_t *CustomDecal_LoadImage( const char *path, void *raw, int size )
|
|
|
|
{
|
|
|
|
const char *testname;
|
|
|
|
|
|
|
|
// this way we limit file types
|
|
|
|
if( !Q_stricmp( COM_FileExtension( path ), "png" ))
|
|
|
|
testname = "#logo.png";
|
|
|
|
else testname = "#logo.bmp";
|
|
|
|
|
|
|
|
Image_SetForceFlags( IL_LOAD_PLAYER_DECAL );
|
|
|
|
|
|
|
|
return FS_LoadImage( testname, raw, size );
|
|
|
|
}
|
|
|
|
|
|
|
|
static qboolean CustomDecal_Validate( const char *path, void *raw, int nFileSize )
|
|
|
|
{
|
|
|
|
rgbdata_t *test = CustomDecal_LoadImage( path, raw, nFileSize );
|
|
|
|
|
|
|
|
if( test )
|
|
|
|
{
|
|
|
|
// all's ok, logo is valid
|
|
|
|
FS_FreeImage( test );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void COM_ClearCustomizationList( customization_t *pHead, qboolean bCleanDecals )
|
|
|
|
{
|
|
|
|
customization_t *pCurrent;
|
|
|
|
customization_t *pNext;
|
|
|
|
|
|
|
|
for( pCurrent = pHead->pNext; pCurrent != NULL; pCurrent = pNext )
|
|
|
|
{
|
|
|
|
pNext = pCurrent->pNext;
|
|
|
|
|
|
|
|
if( pCurrent->bInUse && pCurrent->pBuffer )
|
|
|
|
Mem_Free( pCurrent->pBuffer );
|
|
|
|
|
|
|
|
if( pCurrent->bInUse && pCurrent->pInfo )
|
|
|
|
{
|
|
|
|
#if !XASH_DEDICATED
|
|
|
|
if( pCurrent->resource.type == t_decal )
|
|
|
|
{
|
|
|
|
if( bCleanDecals && CL_Active( ))
|
|
|
|
ref.dllFuncs.R_DecalRemoveAll( pCurrent->nUserData1 );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
FS_FreeImage( pCurrent->pInfo );
|
|
|
|
}
|
|
|
|
Mem_Free( pCurrent );
|
|
|
|
}
|
|
|
|
|
|
|
|
pHead->pNext = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
qboolean COM_CreateCustomization( customization_t *pListHead, resource_t *pResource, int playernumber, int flags, customization_t **pOut, int *nLumps )
|
|
|
|
{
|
|
|
|
qboolean bError = false;
|
|
|
|
fs_offset_t checksize = 0;
|
|
|
|
customization_t *pCust;
|
|
|
|
|
|
|
|
if( pOut ) *pOut = NULL;
|
|
|
|
|
|
|
|
pCust = Z_Calloc( sizeof( customization_t ));
|
|
|
|
pCust->resource = *pResource;
|
|
|
|
|
|
|
|
if( pResource->nDownloadSize <= 0 )
|
|
|
|
goto CustomizationError;
|
|
|
|
|
|
|
|
pCust->bInUse = true;
|
|
|
|
|
|
|
|
if( FBitSet( flags, FCUST_FROMHPAK ))
|
|
|
|
{
|
|
|
|
if( !HPAK_GetDataPointer( CUSTOM_RES_PATH, pResource, (byte **)&pCust->pBuffer, NULL ))
|
|
|
|
bError = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
pCust->pBuffer = FS_LoadFile( pResource->szFileName, &checksize, true );
|
|
|
|
if( (int)checksize != pCust->resource.nDownloadSize )
|
|
|
|
bError = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( bError )
|
|
|
|
goto CustomizationError;
|
|
|
|
|
|
|
|
if( FBitSet( pCust->resource.ucFlags, RES_CUSTOM ) && pCust->resource.type == t_decal )
|
|
|
|
{
|
|
|
|
pCust->resource.playernum = playernumber;
|
|
|
|
|
|
|
|
if( CustomDecal_Validate( pResource->szFileName, pCust->pBuffer, pResource->nDownloadSize ))
|
|
|
|
{
|
|
|
|
if( !FBitSet( flags, FCUST_IGNOREINIT ))
|
|
|
|
{
|
|
|
|
if( pResource->nDownloadSize >= (1 * 1024) && pResource->nDownloadSize <= ( 128 * 1024 ))
|
|
|
|
{
|
|
|
|
pCust->bTranslated = true;
|
|
|
|
pCust->nUserData1 = 0;
|
|
|
|
pCust->nUserData2 = 1;
|
|
|
|
|
|
|
|
if( !FBitSet( flags, FCUST_WIPEDATA ))
|
|
|
|
pCust->pInfo = CustomDecal_LoadImage( pResource->szFileName, pCust->pBuffer, pCust->resource.nDownloadSize );
|
|
|
|
else pCust->pInfo = NULL;
|
|
|
|
if( nLumps ) *nLumps = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Con_Printf( S_WARN "Ignoring custom decal \"%s\": wrong size (%i bytes)\n", pResource->szFileName, pResource->nDownloadSize );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( pOut ) *pOut = pCust;
|
|
|
|
pCust->pNext = pListHead->pNext;
|
|
|
|
pListHead->pNext = pCust;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
CustomizationError:
|
|
|
|
if( pCust->pBuffer )
|
|
|
|
Mem_Free( pCust->pBuffer );
|
|
|
|
|
|
|
|
if( pCust->pInfo )
|
|
|
|
Mem_Free( pCust->pInfo );
|
|
|
|
Mem_Free( pCust );
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int COM_SizeofResourceList( resource_t *pList, resourceinfo_t *ri )
|
|
|
|
{
|
|
|
|
int nSize = 0;
|
|
|
|
resource_t *p;
|
|
|
|
|
|
|
|
memset( ri, 0, sizeof( *ri ));
|
|
|
|
|
|
|
|
for( p = pList->pNext; p != pList; p = p->pNext )
|
|
|
|
{
|
|
|
|
nSize += p->nDownloadSize;
|
|
|
|
|
|
|
|
if( p->type == t_model && p->nIndex == 1 )
|
|
|
|
ri->info[t_world].size += p->nDownloadSize;
|
|
|
|
else ri->info[p->type].size += p->nDownloadSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nSize;
|
|
|
|
}
|