diff --git a/engine/client/ref_common.c b/engine/client/ref_common.c index be32ca7c..8e4aaf81 100644 --- a/engine/client/ref_common.c +++ b/engine/client/ref_common.c @@ -393,6 +393,10 @@ static ref_api_t gEngfuncs = pfnDrawNormalTriangles, pfnDrawTransparentTriangles, &clgame.drawFuncs +#if XASH_PSP + ,P5Ram_Alloc, + P5Ram_Free +#endif }; static void R_UnloadProgs( void ) diff --git a/engine/platform/platform.h b/engine/platform/platform.h index e40fe461..4939e155 100644 --- a/engine/platform/platform.h +++ b/engine/platform/platform.h @@ -42,6 +42,8 @@ void Platform_MessageBox( const char *title, const char *message, qboolean paren void Platform_ReadCmd( const char *fname, int *argc, char **argv ); SceUID Platform_LoadModule( const char *filename, int mpid, SceSize argsize, void *argp ); int Platform_UnloadModule( SceUID modid, int *sce_code ); + +#include "psp/p5ram_psp.h" #endif #if XASH_ANDROID const char *Android_GetAndroidID( void ); diff --git a/engine/platform/psp/p5ram_psp.c b/engine/platform/psp/p5ram_psp.c new file mode 100644 index 00000000..f2a8cce7 --- /dev/null +++ b/engine/platform/psp/p5ram_psp.c @@ -0,0 +1,163 @@ +/* +p5ram_psp.c - PSP P5 memory allocator +Copyright (C) 2022 Sergey Galushko + +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 +#include +#include + +#include +#include +#include "p5ram_psp.h" + +#define P5RAM_ALIGN( x, a ) ((( x ) + (( typeof( x ))( a ) - 1 )) & ~( typeof( x )( a ) - 1 )) + +#define P5RAM_CHECK( addr ) ((( unsigned int )addr >= ( unsigned int )p5ram_addr) && (( unsigned int )addr < ( unsigned int )p5ram_addr + p5ram_size)) + +#define P5RAM_FLAG_INIT 0x01 +#define P5RAM_FLAG_SUSPENDED 0x02 + +typedef struct p5ram_info_s +{ + SceUID uid; + size_t size; + struct p5ram_info_s *next; +}p5ram_info_t; + +static unsigned char p5ram_flags = 0x00; +static p5ram_info_t *p5ram_poolchain = NULL; +static void *p5ram_addr; +static unsigned int p5ram_size; + +int P5Ram_Init( void ) +{ + int result; + + if( p5ram_flags & P5RAM_FLAG_INIT ) + return -1; + + result = sceKernelVolatileMemLock( 0, &p5ram_addr, &p5ram_size ); + if( result == 0 ) + p5ram_flags |= P5RAM_FLAG_INIT; + + return result; +} + +void *P5Ram_Alloc( size_t size ) +{ + SceUID uid; + void *ptr; + + if(!( p5ram_flags & P5RAM_FLAG_INIT )) + return NULL; + + uid = sceKernelAllocPartitionMemory( 5, "USER P5", PSP_SMEM_Low, size + /*sizeof( p5ram_info_t )*/64, NULL ); + if( uid < 0 ) return NULL; + + ptr = sceKernelGetBlockHeadAddr( uid ); + (( p5ram_info_t* )ptr )->uid = uid; + (( p5ram_info_t* )ptr )->size = size; + (( p5ram_info_t* )ptr )->next = p5ram_poolchain; + + p5ram_poolchain = ptr; + + return ptr + /*sizeof( p5ram_info_t )*/64; +} + +void P5Ram_Free( void *ptr ) +{ + p5ram_info_t *info, *next_ptr; + + if( !( p5ram_flags & P5RAM_FLAG_INIT ) || ptr == NULL ) return; + + info = ( p5ram_info_t* )( ptr - /*sizeof( p5ram_info_t )*/64); + + if( info == p5ram_poolchain ) + { + p5ram_poolchain = p5ram_poolchain->next; + } + else + { + next_ptr = p5ram_poolchain; + while( next_ptr ) + { + if( next_ptr->next == info ) + { + next_ptr->next = info->next; + break; + } + next_ptr = next_ptr->next; + } + } + + sceKernelFreePartitionMemory( info->uid ); +} + +void P5Ram_FreeAll( void ) +{ + p5ram_info_t *next_ptr; + + while( p5ram_poolchain ) + { + next_ptr = p5ram_poolchain->next; + sceKernelFreePartitionMemory( p5ram_poolchain->uid ); + p5ram_poolchain = next_ptr; + } +} + +void P5Ram_Shutdown( void ) +{ + if( !( p5ram_flags & P5RAM_FLAG_INIT )) + return; + + P5Ram_FreeAll(); + sceKernelVolatileMemUnlock( 0 ); + + p5ram_flags &= ~P5RAM_FLAG_INIT; +} + +void P5Ram_PowerCallback( int count, int arg, void *common ) +{ + if( !( p5ram_flags & ( P5RAM_FLAG_INIT | P5RAM_FLAG_SUSPENDED ))) + return; + + if ( arg & PSP_POWER_CB_POWER_SWITCH || arg & PSP_POWER_CB_SUSPENDING ) + { + P5Ram_Shutdown(); + p5ram_flags |= P5RAM_FLAG_SUSPENDED; + } + else if ( arg & PSP_POWER_CB_RESUMING ) + { + } + else if ( arg & PSP_POWER_CB_RESUME_COMPLETE ) + { + P5Ram_Init(); + p5ram_flags &= ~P5RAM_FLAG_SUSPENDED; + } +} + +#ifdef P5RAM_DEBUG +void P5Ram_Print( void ) +{ + p5ram_info_t *next_ptr; + + printf("+++++++++++++++++++++++++++++\n"); + next_ptr = p5ram_poolchain; + while( next_ptr ) + { + printf("P5 ALLOC [ 0x%08X 0x%08X 0x%08X 0x%08X ]\n", next_ptr, next_ptr->uid, next_ptr->size, next_ptr->next ); + next_ptr = next_ptr->next; + } + printf("+++++++++++++++++++++++++++++\n"); +} +#endif diff --git a/engine/platform/psp/p5ram_psp.h b/engine/platform/psp/p5ram_psp.h new file mode 100644 index 00000000..dc424c27 --- /dev/null +++ b/engine/platform/psp/p5ram_psp.h @@ -0,0 +1,38 @@ +/* +p5ram_psp.h - PSP P5 memory allocator header +Copyright (C) 2022 Sergey Galushko + +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. +*/ +#ifndef P5RAM_PSP_H +#define P5RAM_PSP_H + +//#define P5RAM_DEBUG + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +int P5Ram_Init( void ); +void *P5Ram_Alloc( size_t size ); +void P5Ram_Free( void *ptr ); +void P5Ram_FreeAll( void ); +void P5Ram_Shutdown( void ); +void P5Ram_PowerCallback( int count, int arg, void *common ); +#ifdef P5RAM_DEBUG +void P5Ram_Print( void ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // P5RAM_PSP_H diff --git a/engine/platform/psp/sys_psp.c b/engine/platform/psp/sys_psp.c index 9c56ecc4..bdb0b2d5 100644 --- a/engine/platform/psp/sys_psp.c +++ b/engine/platform/psp/sys_psp.c @@ -30,31 +30,39 @@ PSP_MAIN_THREAD_ATTR( PSP_THREAD_ATTR_USER | PSP_THREAD_ATTR_VFPU ); PSP_MAIN_THREAD_STACK_SIZE_KB( 512 ); PSP_HEAP_SIZE_KB( -3 * 1024 ); /* 3 MB for prx modules */ -/* Exit callback */ -static int exit_callback( int arg1, int arg2, void *common ) +static int Platform_ExitCallback( int count, int arg, void *common ) { host.crashed = true; return 0; } -/* Callback thread */ -static int CallbackThread( SceSize args, void *argp ) +static int Platform_PowerCallback( int count, int arg, void *common ) +{ + P5Ram_PowerCallback( count, arg, common ); + return 0; +} + +static int Platform_CallbackThread( SceSize args, void *argp ) { int cbid; - cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL); - sceKernelRegisterExitCallback(cbid); + cbid = sceKernelCreateCallback( "Exit Callback", Platform_ExitCallback, NULL ); + sceKernelRegisterExitCallback( cbid ); + + cbid = sceKernelCreateCallback( "Power Callback", Platform_PowerCallback, NULL ); + scePowerRegisterCallback( 0, cbid ); + sceKernelSleepThreadCB(); return 0; } /* Sets up the callback thread and returns its thread id */ -static int SetupCallbacks( void ) +static int Platform_SetupCallbacks( void ) { int thid = 0; - thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0); + thid = sceKernelCreateThread("update_thread", Platform_CallbackThread, 0x11, 0xFA0, 0, 0); if(thid >= 0) { sceKernelStartThread(thid, 0, 0); @@ -259,7 +267,7 @@ int Platform_UnloadModule( SceUID modid, int *sce_code ) *sce_code = sceKernelUnloadModule( modid ); return ( ( ( *sce_code ) < 0 ) ? -2 : 0 ); } - +#include "vfs_psp.h" void Platform_Init( void ) { SceUID kamID; @@ -269,7 +277,7 @@ void Platform_Init( void ) pspSdkDisableFPUExceptions(); // exit callback thread - SetupCallbacks(); + Platform_SetupCallbacks(); // set max cpu/gpu frequency scePowerSetClockFrequency( 333, 333, 166 ); @@ -283,10 +291,14 @@ void Platform_Init( void ) result = kaGeEdramSetSize( result ); Platform_UnloadModule( kamID, &result ); } + + // P5 Ram init + P5Ram_Init(); } void Platform_Shutdown( void ) { + P5Ram_Shutdown(); #if XASH_PROFILING gprof_cleanup(); #endif diff --git a/engine/ref_api.h b/engine/ref_api.h index 3539a2a1..0875c77b 100644 --- a/engine/ref_api.h +++ b/engine/ref_api.h @@ -431,6 +431,10 @@ typedef struct ref_api_s void (*pfnDrawNormalTriangles)( void ); void (*pfnDrawTransparentTriangles)( void ); render_interface_t *drawFuncs; +#if XASH_PSP + void *(*P5Ram_Alloc)( size_t size ); + void (*P5Ram_Free)( void *ptr ); +#endif } ref_api_t; struct mip_s; diff --git a/engine/server/sv_save.c b/engine/server/sv_save.c index 0a82412b..eafe5c96 100644 --- a/engine/server/sv_save.c +++ b/engine/server/sv_save.c @@ -291,7 +291,11 @@ static void InitEntityTable( SAVERESTOREDATA *pSaveData, int entityCount ) ENTITYTABLE *pTable; int i; +#if XASH_PSP + pSaveData->pTable = P5Ram_Alloc( sizeof( ENTITYTABLE ) * entityCount ); +#else pSaveData->pTable = Mem_Calloc( host.mempool, sizeof( ENTITYTABLE ) * entityCount ); +#endif pSaveData->tableCount = entityCount; // setup entitytable @@ -607,8 +611,13 @@ static SAVERESTOREDATA *SaveInit( int size, int tokenCount ) { SAVERESTOREDATA *pSaveData; +#if XASH_PSP + pSaveData = P5Ram_Alloc( sizeof( SAVERESTOREDATA ) + size ); + pSaveData->pTokens = (char **)P5Ram_Alloc( tokenCount * sizeof( char* )); +#else pSaveData = Mem_Calloc( host.mempool, sizeof( SAVERESTOREDATA ) + size ); pSaveData->pTokens = (char **)Mem_Calloc( host.mempool, tokenCount * sizeof( char* )); +#endif pSaveData->tokenCount = tokenCount; pSaveData->pBaseData = (char *)(pSaveData + 1); // skip the save structure); @@ -657,20 +666,32 @@ static void SaveFinish( SAVERESTOREDATA *pSaveData ) if( pSaveData->pTokens ) { +#if XASH_PSP + P5Ram_Free( pSaveData->pTokens ); +#else Mem_Free( pSaveData->pTokens ); +#endif pSaveData->pTokens = NULL; pSaveData->tokenCount = 0; } if( pSaveData->pTable ) { +#if XASH_PSP + P5Ram_Free( pSaveData->pTable ); +#else Mem_Free( pSaveData->pTable ); +#endif pSaveData->pTable = NULL; pSaveData->tableCount = 0; } svgame.globals->pSaveData = NULL; +#if XASH_PSP + P5Ram_Free( pSaveData ); +#else Mem_Free( pSaveData ); +#endif } /* @@ -2246,7 +2267,11 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment ) // allocate a table for the strings, and parse the table if( tokenSize > 0 ) { +#if XASH_PSP + pTokenList = P5Ram_Alloc( tokenCount * sizeof( char* )); +#else pTokenList = Mem_Calloc( host.mempool, tokenCount * sizeof( char* )); +#endif // make sure the token strings pointed to by the pToken hashtable. for( i = 0; i < tokenCount; i++ ) @@ -2274,8 +2299,13 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment ) if( Q_stricmp( pFieldName, "GameHeader" )) { Q_strncpy( comment, "", MAX_STRING ); +#if XASH_PSP + if( pTokenList ) P5Ram_Free( pTokenList ); + if( pSaveData ) P5Ram_Free( pSaveData ); +#else if( pTokenList ) Mem_Free( pTokenList ); if( pSaveData ) Mem_Free( pSaveData ); +#endif FS_Close( f ); return 0; } @@ -2325,8 +2355,13 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment ) } // delete the string table we allocated +#if XASH_PSP + if( pTokenList ) P5Ram_Free( pTokenList ); + if( pSaveData ) P5Ram_Free( pSaveData ); +#else if( pTokenList ) Mem_Free( pTokenList ); if( pSaveData ) Mem_Free( pSaveData ); +#endif FS_Close( f ); // at least mapname should be filled diff --git a/ref_gu/gu_image.c b/ref_gu/gu_image.c index b00cc9b9..214405ea 100644 --- a/ref_gu/gu_image.c +++ b/ref_gu/gu_image.c @@ -20,10 +20,10 @@ GNU General Public License for more details. #define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2) -static gl_texture_t gl_textures[MAX_TEXTURES]; +static gl_texture_t gl_textures[MAX_TEXTURES]; static gl_texture_t* gl_texturesHashTable[TEXTURES_HASH_SIZE]; -static uint gl_numTextures; -static byte *palette_332 = NULL; +static uint gl_numTextures; +static byte* gl_palette_332 = NULL; /* num_colors = PALETTE_BLOCKS x 16 (16-bit CLUT) @@ -65,7 +65,7 @@ GL_Bind void GL_Bind( GLint tmu, GLenum texnum ) { gl_texture_t *texture; - int i, offset, width, height; + int i, offset, width, height; // missed or invalid texture? if( texnum <= 0 || texnum >= MAX_TEXTURES ) @@ -84,7 +84,7 @@ void GL_Bind( GLint tmu, GLenum texnum ) if( texture->format == GU_PSM_T8 ) { sceGuClutMode( PALETTE_FORMAT, 0, 0xff, 0 ); - sceGuClutLoad( PALETTE_BLOCKS, texture->dstPalette ? texture->dstPalette : palette_332 ); + sceGuClutLoad( PALETTE_BLOCKS, texture->dstPalette ); } // Set texture parameters @@ -108,7 +108,7 @@ void GL_Bind( GLint tmu, GLenum texnum ) sceGuTexFilter( GU_LINEAR, GU_LINEAR ); } - if( FBitSet( texture->flags, TF_CLAMP ) || FBitSet( texture->flags, TF_BORDER ) ) + if( FBitSet( texture->flags, TF_CLAMP ) || FBitSet( texture->flags, TF_BORDER )) sceGuTexWrap( GU_CLAMP, GU_CLAMP ); else sceGuTexWrap( GU_REPEAT, GU_REPEAT ); @@ -122,8 +122,8 @@ void GL_Bind( GLint tmu, GLenum texnum ) offset = texture->width * texture->height * texture->bpp; for ( i = 1; i < texture->numMips; i++ ) { - width = Q_max( TEXTURE_SIZE_MIN, ( texture->width >> i ) ); - height = Q_max( TEXTURE_SIZE_MIN, ( texture->height >> i ) ); + width = Q_max( TEXTURE_SIZE_MIN, ( texture->width >> i )); + height = Q_max( TEXTURE_SIZE_MIN, ( texture->height >> i )); sceGuTexImage( i, width, height, width, &texture->dstTexture[offset] ); offset += width * height * texture->bpp; } @@ -138,7 +138,7 @@ GL_CalcImageSize */ static size_t GL_CalcImageSize( pixformat_t format, int width, int height, int depth ) { - size_t size = 0; + size_t size = 0; // check the depth error depth = Q_max( 1, depth ); @@ -184,14 +184,14 @@ GL_CalcTextureSize */ static size_t GL_CalcTextureSize( int format, int width, int height, byte *outBpp ) { - size_t size = 0; - byte bpp = 0; + size_t size = 0; + byte bpp = 0; switch( format ) { case GU_PSM_T4: case GU_PSM_DXT1: - size = ( ( width * height ) >> 1 ); + size = (( width * height ) >> 1 ); break; case GU_PSM_T8: case GU_PSM_DXT3: @@ -223,8 +223,8 @@ static size_t GL_CalcTextureSize( int format, int width, int height, byte *outBp static int GL_CalcMipmapCount( gl_texture_t *tex, qboolean haveBuffer, size_t *mipSize ) { - int width, height; - int mipCount; + int width, height; + int mipCount; Assert( tex != NULL ); @@ -233,19 +233,19 @@ static int GL_CalcMipmapCount( gl_texture_t *tex, qboolean haveBuffer, size_t *m #if 0 // brush model only - if( !FBitSet( tex->flags, TF_ALLOW_EMBOSS ) ) + if( !FBitSet( tex->flags, TF_ALLOW_EMBOSS )) return 1; #endif // generate mip-levels by user request - if( FBitSet( tex->flags, TF_NOMIPMAP ) ) + if( FBitSet( tex->flags, TF_NOMIPMAP )) return 1; // 8 levels - 7 + 1 base for( mipCount = 1; mipCount < 8; mipCount++ ) { - width = Q_max( TEXTURE_SIZE_MIN, ( tex->width >> mipCount ) ); - height = Q_max( TEXTURE_SIZE_MIN, ( tex->height >> mipCount ) ); + width = Q_max( TEXTURE_SIZE_MIN, ( tex->width >> mipCount )); + height = Q_max( TEXTURE_SIZE_MIN, ( tex->height >> mipCount )); if( width == TEXTURE_SIZE_MIN && height == TEXTURE_SIZE_MIN ) break; @@ -264,9 +264,9 @@ GL_SetTextureDimensions */ static void GL_SetTextureDimensions( gl_texture_t *tex, int width, int height ) { - int maxTextureSize = glConfig.max_texture_size; - int step = (int)gl_round_down->value; - int scaled_width, scaled_height; + int maxTextureSize = glConfig.max_texture_size; + int step = (int)gl_round_down->value; + int scaled_width, scaled_height; Assert( tex != NULL ); @@ -276,12 +276,12 @@ static void GL_SetTextureDimensions( gl_texture_t *tex, int width, int height ) for( scaled_width = 1; scaled_width < width; scaled_width <<= 1 ); - if( step > 0 && width < scaled_width && ( step == 1 || ( scaled_width - width ) > ( scaled_width >> step ) ) ) + if( step > 0 && width < scaled_width && ( step == 1 || ( scaled_width - width ) > ( scaled_width >> step ))) scaled_width >>= 1; for( scaled_height = 1; scaled_height < height; scaled_height <<= 1 ); - if( step > 0 && height < scaled_height && ( step == 1 || ( scaled_height - height ) > ( scaled_height >> step ) ) ) + if( step > 0 && height < scaled_height && ( step == 1 || ( scaled_height - height ) > ( scaled_height >> step ))) scaled_height >>= 1; width = scaled_width; @@ -342,7 +342,7 @@ static void GL_SetTextureFormat( gl_texture_t *tex, pixformat_t format, int chan case PF_BGRA_32: case PF_RGB_24: case PF_BGR_24: - if ( IsLightMap( tex ) ) + if ( IsLightMap( tex )) tex->format = GU_PSM_8888; else if( haveAlpha ) tex->format = GU_PSM_4444; @@ -464,7 +464,7 @@ void GL_ResampleTexture8(const byte *source, int inWidth, int inHeight, byte *de byte *out; const byte *inrow; uint frac; - int i, j; + int i, j; if( !source ) return; @@ -659,7 +659,7 @@ PC_SWF - Xash3d Software format mask void GL_PixelConverter( byte *dst, const byte *src, int size, int inFormat, int outFormat ) { int i; - byte color[4]; + byte color[4]; color[0] = color[1] = color[2] = color[3] = 0xff; @@ -789,14 +789,14 @@ fast swizzling */ static void GL_TextureSwizzle( byte *dst, const byte *src, uint width, uint height ) { - uint blockx, blocky; - uint j; - uint width_blocks = ( width / 16 ); - uint height_blocks = ( height / 8 ); - uint src_pitch = ( width - 16 ) / 4; - uint src_row = width * 8; + uint blockx, blocky; + uint j; + uint width_blocks = ( width / 16 ); + uint height_blocks = ( height / 8 ); + uint src_pitch = ( width - 16 ) / 4; + uint src_row = width * 8; const byte* ysrc = src; - uint* dst32 = ( uint* )dst; + uint* dst32 = ( uint* )dst; for ( blocky = 0; blocky < height_blocks; ++blocky ) { @@ -827,15 +827,13 @@ upload texture into memory */ static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic ) { - size_t texSize; - uint width, height; - uint i; - uint offset, mipOffset; - qboolean normalMap; - qboolean swizzle; - void *volBuff; - unsigned int volSize; - int volUid; + size_t texSize; + uint width, height; + uint i; + uint offset, mipOffset; + qboolean normalMap; + qboolean swizzle; + byte *tempBuff; // dedicated server if( !glw_state.initialized ) @@ -869,11 +867,6 @@ static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic ) swizzle = IsLightMap( tex ) ? false : true; mipOffset = 0; - // Volatile memory for temporary buffer - volUid = sceKernelVolatileMemLock( 0, &volBuff, &volSize ); - if( volUid != 0) - gEngfuncs.Host_Error( "GL_UploadTexture: volatile memory lock error ( 0x%08x )\n", volUid ); - // Check allocation size if( tex->dstTexture && ( tex->size != texSize ) ) { @@ -894,10 +887,7 @@ static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic ) { tex->dstTexture = ( byte* )memalign( 16, texSize ); if ( !tex->dstTexture ) - { - sceKernelVolatileMemUnlock( 0 ); gEngfuncs.Host_Error( "GL_UploadTexture: %s out of memory for texture ( %lu )\n", tex->name, texSize ); - } } else SetBits( tex->flags, TF_IMG_INVRAM ); } @@ -914,16 +904,21 @@ static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic ) { tex->dstPalette = ( byte* )memalign( 16, PALETTE_SIZE ); if ( !tex->dstPalette ) - { - sceKernelVolatileMemUnlock( 0 ); gEngfuncs.Host_Error( "GL_UploadTexture: %s out of memory for palette ( %lu )\n", tex->name, PALETTE_SIZE ); - } } // Load palette - GL_PixelConverter( tex->dstPalette, pic->palette, 256, PC_SWF( pic->type ), PC_HWF( PALETTE_FORMAT ) ); + GL_PixelConverter( tex->dstPalette, pic->palette, 256, PC_SWF( pic->type ), PC_HWF( PALETTE_FORMAT )); sceKernelDcacheWritebackRange( tex->dstPalette, PALETTE_SIZE ); } + else tex->dstPalette = gl_palette_332; + + // Volatile memory for temporary buffer + if( swizzle ) + { + tempBuff = gEngfuncs.P5Ram_Alloc( texSize ); + if( !tempBuff ) gEngfuncs.Host_Error( "GL_UploadTexture: temporary memory error\n" ); + } // Load base + mip texture for( i = 0; i < tex->numMips; i++ ) @@ -931,66 +926,83 @@ static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic ) width = Q_max( TEXTURE_SIZE_MIN, ( tex->width >> i ) ); height = Q_max( TEXTURE_SIZE_MIN, ( tex->height >> i ) ); - if( ( pic->width != width ) || ( pic->height != height ) ) - GL_ResampleTexture8( pic->buffer, pic->width, pic->height, swizzle ? volBuff : ( tex->dstTexture + mipOffset ), width, height ); - else memcpy( swizzle ? volBuff : ( tex->dstTexture + mipOffset ), pic->buffer, offset ); + if(( pic->width != width ) || ( pic->height != height )) + GL_ResampleTexture8( pic->buffer, pic->width, pic->height, swizzle ? tempBuff : ( tex->dstTexture + mipOffset ), width, height ); + else memcpy( swizzle ? tempBuff : ( tex->dstTexture + mipOffset ), pic->buffer, offset ); - if(swizzle) GL_TextureSwizzle( tex->dstTexture + mipOffset, volBuff, width, height ); + if(swizzle) GL_TextureSwizzle( tex->dstTexture + mipOffset, tempBuff, width, height ); mipOffset += GL_CalcTextureSize( tex->format, width, height, NULL ); } - if(swizzle) SetBits( tex->flags, TF_IMG_SWIZZLED ); - } - else if( pic->type == PF_RGB_5650 || pic->type == PF_RGBA_5551 || pic->type == PF_RGBA_4444 ) - { - if( ( pic->width != tex->width ) || ( pic->height != tex->height ) ) - { - for( i = 0; i < tex->height; i++ ) - { - memcpy( swizzle ? ( volBuff + tex->width * tex->bpp * i ) : ( tex->dstTexture + tex->width * tex->bpp * i ), - ( pic->buffer + pic->width * tex->bpp * i ), pic->width * tex->bpp ); - } - } - else memcpy( swizzle ? volBuff : tex->dstTexture, pic->buffer, offset ); if( swizzle ) { - GL_TextureSwizzle( tex->dstTexture, volBuff, tex->width * tex->bpp, tex->height ); + gEngfuncs.P5Ram_Free( tempBuff ); + SetBits( tex->flags, TF_IMG_SWIZZLED ); + } + } + else if( pic->type == PF_RGB_5650 || pic->type == PF_RGBA_5551 || pic->type == PF_RGBA_4444 ) + { + if( swizzle ) + { + tempBuff = gEngfuncs.P5Ram_Alloc( texSize ); + if( !tempBuff ) gEngfuncs.Host_Error( "GL_UploadTexture: temporary memory error\n" ); + } + + if(( pic->width != tex->width ) || ( pic->height != tex->height )) + { + for( i = 0; i < tex->height; i++ ) + { + memcpy( swizzle ? ( tempBuff + tex->width * tex->bpp * i ) : ( tex->dstTexture + tex->width * tex->bpp * i ), + ( pic->buffer + pic->width * tex->bpp * i ), pic->width * tex->bpp ); + } + } + else memcpy( swizzle ? tempBuff : tex->dstTexture, pic->buffer, offset ); + + if( swizzle ) + { + GL_TextureSwizzle( tex->dstTexture, tempBuff, tex->width * tex->bpp, tex->height ); + gEngfuncs.P5Ram_Free( tempBuff ); SetBits( tex->flags, TF_IMG_SWIZZLED ); } } else // RGBA32 { - if( ( pic->width != tex->width ) || ( pic->height != tex->height ) ) - { - GL_ResampleTexture32( pic->buffer, pic->width, pic->height, volBuff, tex->width, tex->height, normalMap ); - offset = tex->width * tex->height * 4; // 4 src bpp - } - else memcpy( volBuff, pic->buffer, offset ); + if(( pic->width != tex->width ) || ( pic->height != tex->height )) + offset = tex->width * tex->height * 4; // src size + + tempBuff = gEngfuncs.P5Ram_Alloc( swizzle ? ( texSize + offset ) : texSize ); + if( !tempBuff ) gEngfuncs.Host_Error( "GL_UploadTexture: temporary memory error\n" ); + + if(( pic->width != tex->width ) || ( pic->height != tex->height )) + GL_ResampleTexture32( pic->buffer, pic->width, pic->height, tempBuff, tex->width, tex->height, normalMap ); + else memcpy( tempBuff, pic->buffer, offset ); /* if( !FBitSet( tex->flags, TF_NOMIPMAP ) && FBitSet( pic->flags, IMAGE_ONEBIT_ALPHA )) - volBuff = GL_ApplyFilter( volBuff, tex->width, tex->height ); + tempBuff = GL_ApplyFilter( tempBuff, tex->width, tex->height ); */ if( tex->format == GU_PSM_8888 ) { if ( swizzle ) { - GL_TextureSwizzle( tex->dstTexture, volBuff, tex->width * tex->bpp, tex->height ); + GL_TextureSwizzle( tex->dstTexture, tempBuff, tex->width * tex->bpp, tex->height ); SetBits( tex->flags, TF_IMG_SWIZZLED ); } - else memcpy( tex->dstTexture, volBuff, texSize ); + else memcpy( tex->dstTexture, tempBuff, texSize ); } else { - GL_PixelConverter( swizzle ? (volBuff + offset) : tex->dstTexture, volBuff, tex->width * tex->height, PC_SWF( pic->type ), PC_HWF( tex->format ) ); + if( tex->format == GU_PSM_T8 ) tex->dstPalette = gl_palette_332; + + GL_PixelConverter( swizzle ? (tempBuff + offset) : tex->dstTexture, tempBuff, tex->width * tex->height, PC_SWF( pic->type ), PC_HWF( tex->format ) ); if( swizzle ) { - GL_TextureSwizzle( tex->dstTexture, volBuff + offset, tex->width * tex->bpp, tex->height ); + GL_TextureSwizzle( tex->dstTexture, tempBuff + offset, tex->width * tex->bpp, tex->height ); SetBits( tex->flags, TF_IMG_SWIZZLED ); } } + gEngfuncs.P5Ram_Free( tempBuff ); } - sceKernelVolatileMemUnlock( 0 ); sceKernelDcacheWritebackRange( tex->dstTexture, texSize ); tex->size = texSize; @@ -1008,8 +1020,8 @@ GL_UpdateTexture qboolean GL_UpdateTexture( int texnum, int xoff, int yoff, int width, int height, const void *buffer ) { gl_texture_t *tex; - size_t texsize; - byte *dst, *src; + size_t texsize; + byte *dst, *src; // missed or invalid texture? if(( texnum <= 0 ) || ( texnum >= MAX_TEXTURES )) @@ -1030,7 +1042,7 @@ qboolean GL_UpdateTexture( int texnum, int xoff, int yoff, int width, int height if( !FBitSet( tex->flags, TF_IMG_UPLOADED ) ) { - tex->size = GL_CalcTextureSize( tex->format, tex->width, tex->height, &tex->bpp ); + tex->size = GL_CalcTextureSize( tex->format, tex->width, tex->height, &tex->bpp ); tex->numMips = 1; tex->dstPalette = NULL; @@ -1055,7 +1067,7 @@ qboolean GL_UpdateTexture( int texnum, int xoff, int yoff, int width, int height dst += tex->width * tex->bpp; src += width * tex->bpp; } - + sceKernelDcacheWritebackRange( tex->dstTexture, tex->size ); return true; } @@ -1069,8 +1081,8 @@ do specified actions on pixels */ static void GL_ProcessImage( gl_texture_t *tex, rgbdata_t *pic ) { - float emboss_scale = 0.0f; - uint img_flags = 0; + float emboss_scale = 0.0f; + uint img_flags = 0; // force upload texture as RGB or RGBA (detail textures requires this) if( tex->flags & TF_FORCE_COLOR ) pic->flags |= IMAGE_HAS_COLOR; @@ -1250,7 +1262,7 @@ static void GL_DeleteTexture( gl_texture_t *tex ) if( tex->original ) gEngfuncs.FS_FreeImage( tex->original ); - if( tex->dstPalette ) + if( tex->dstPalette && tex->dstPalette != gl_palette_332 ) free( tex->dstPalette ); if( tex->dstTexture ) @@ -1306,7 +1318,7 @@ GL_LoadTexture int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags ) { gl_texture_t *tex; - rgbdata_t *pic; + rgbdata_t *pic; uint picFlags = 0; if( !GL_CheckTexName( name )) @@ -1357,7 +1369,7 @@ int GL_LoadTextureArray( const char **names, int flags ) #if 1 return 0; #else - rgbdata_t *pic, *src; + rgbdata_t *pic, *src; char basename[256]; uint numLayers = 0; uint picFlags = 0; @@ -1544,7 +1556,7 @@ creates texture from buffer int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags ) { qboolean update = FBitSet( flags, TF_UPDATE ) ? true : false; - int datasize = 1; + int datasize = 1; rgbdata_t r_empty; if( FBitSet( flags, TF_ARB_16BIT )) @@ -1864,35 +1876,35 @@ GL_Create332Palette */ static void GL_Create332Palette( void ) { - palette_332 = ( byte* )memalign( 16, PALETTE_SIZE ); - if ( !palette_332 ) + gl_palette_332 = ( byte* )memalign( 16, PALETTE_SIZE ); + if ( !gl_palette_332 ) gEngfuncs.Host_Error( "GL_Create332Palette: out of memory!\n" ); for(int i = 0; i < 256; i++) { #if PALETTE_FORMAT == GU_PSM_5650 - palette_332[i * 2 + 0] = ( i & 0x07 ) << 2; - palette_332[i * 2 + 1] = ( i & 0x38 ) >> 3; - palette_332[i * 2 + 1] |= ( i & 0xc0 ); + gl_palette_332[i * 2 + 0] = ( i & 0x07 ) << 2; + gl_palette_332[i * 2 + 1] = ( i & 0x38 ) >> 3; + gl_palette_332[i * 2 + 1] |= ( i & 0xc0 ); #elif PALETTE_FORMAT == GU_PSM_5551 - palette_332[i * 2 + 0] = ( i & 0x07 ) << 2; - palette_332[i * 2 + 0] |= ( i & 0x08 ) << 4; - palette_332[i * 2 + 1] = ( i & 0x30 ) >> 4; - palette_332[i * 2 + 1] |= ( i & 0xc0 ) >> 1; - palette_332[i * 2 + 1] |= 0x80; + gl_palette_332[i * 2 + 0] = ( i & 0x07 ) << 2; + gl_palette_332[i * 2 + 0] |= ( i & 0x08 ) << 4; + gl_palette_332[i * 2 + 1] = ( i & 0x30 ) >> 4; + gl_palette_332[i * 2 + 1] |= ( i & 0xc0 ) >> 1; + gl_palette_332[i * 2 + 1] |= 0x80; #elif PALETTE_FORMAT == GU_PSM_4444 - palette_332[i * 2 + 0] = ( i & 0x07 ) << 1; - palette_332[i * 2 + 0] |= ( i & 0x38 ) << 2; - palette_332[i * 2 + 1] = ( i & 0xc0 ) >> 4; - palette_332[i * 2 + 1] |= 0xf0; + gl_palette_332[i * 2 + 0] = ( i & 0x07 ) << 1; + gl_palette_332[i * 2 + 0] |= ( i & 0x38 ) << 2; + gl_palette_332[i * 2 + 1] = ( i & 0xc0 ) >> 4; + gl_palette_332[i * 2 + 1] |= 0xf0; #elif PALETTE_FORMAT == GU_PSM_8888 - palette_332[i * 4 + 0] = ( i & 0x07 ) << 5; - palette_332[i * 4 + 1] = ( i & 0x38 ) << 2; - palette_332[i * 4 + 2] = ( i & 0xc0 ); - palette_332[i * 4 + 3] = 0xff; + gl_palette_332[i * 4 + 0] = ( i & 0x07 ) << 5; + gl_palette_332[i * 4 + 1] = ( i & 0x38 ) << 2; + gl_palette_332[i * 4 + 2] = ( i & 0xc0 ); + gl_palette_332[i * 4 + 3] = 0xff; #endif } - sceKernelDcacheWritebackRange( palette_332, PALETTE_SIZE ); + sceKernelDcacheWritebackRange( gl_palette_332, PALETTE_SIZE ); } @@ -2025,8 +2037,8 @@ void R_ShutdownImages( void ) for( i = 0, tex = gl_textures; i < gl_numTextures; i++, tex++ ) GL_DeleteTexture( tex ); - if( palette_332 ) - free( palette_332 ); + if( gl_palette_332 ) + free( gl_palette_332 ); memset( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures )); memset( gl_texturesHashTable, 0, sizeof( gl_texturesHashTable ));