diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cgame/cg_consolecmds.c | 25 | ||||
-rw-r--r-- | src/cgame/cg_local.h | 73 | ||||
-rw-r--r-- | src/cgame/cg_main.c | 2 | ||||
-rw-r--r-- | src/cgame/cg_mem.c | 215 | ||||
-rw-r--r-- | src/game/bg_public.h | 1 | ||||
-rw-r--r-- | src/game/g_local.h | 3 | ||||
-rw-r--r-- | src/game/g_mem.c | 218 | ||||
-rw-r--r-- | src/game/q_shared.h | 5 |
8 files changed, 439 insertions, 103 deletions
diff --git a/src/cgame/cg_consolecmds.c b/src/cgame/cg_consolecmds.c index d0529c62..db613646 100644 --- a/src/cgame/cg_consolecmds.c +++ b/src/cgame/cg_consolecmds.c @@ -179,7 +179,7 @@ CG_StartOrbit_f static void CG_StartOrbit_f( void ) { if (cg_cameraOrbit.value != 0) { - trap_Cvar_Set ("cg_cameraOrbit", "0"); + trap_Cvar_Set("cg_cameraOrbit", "0"); trap_Cvar_Set("cg_thirdPerson", "0"); } else { trap_Cvar_Set("cg_cameraOrbit", "5"); @@ -242,6 +242,28 @@ static void CG_ClientMenu( const char *menuname ) trap_SendConsoleCommand( va( "%s not defined", menuname ) ); } +/* +================== +CG_DecodeMP3_f +================== +*/ +void CG_DecodeMP3_f( void ) +{ + char mp3file[ MAX_QPATH ]; + char wavfile[ MAX_QPATH ]; + + if( trap_Argc() < 2 ) + { + CG_Printf( "usage: decodeMP3 <mp3file> <wavfile>\n" ); + return; + } + + Q_strncpyz( mp3file, CG_Argv( 1 ), MAX_QPATH ); + Q_strncpyz( wavfile, CG_Argv( 2 ), MAX_QPATH ); + + S_decodeMP3( mp3file, wavfile ); +} + typedef struct { char *cmd; void (*function)(void); @@ -270,6 +292,7 @@ static consoleCommand_t commands[] = { { "vtell_attacker", CG_VoiceTellAttacker_f }, { "tcmd", CG_TargetCommand_f }, { "startOrbit", CG_StartOrbit_f }, + { "decodeMP3", CG_DecodeMP3_f }, { "loaddeferred", CG_LoadDeferredPlayers } }; diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index c66ce5fe..0e398258 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -36,56 +36,56 @@ // by the server in the server stored userinfos, or stashed in a cvar. -#define POWERUP_BLINKS 5 +#define POWERUP_BLINKS 5 #define POWERUP_BLINK_TIME 1000 -#define FADE_TIME 200 -#define PULSE_TIME 200 +#define FADE_TIME 200 +#define PULSE_TIME 200 #define DAMAGE_DEFLECT_TIME 100 #define DAMAGE_RETURN_TIME 400 -#define DAMAGE_TIME 500 -#define LAND_DEFLECT_TIME 150 -#define LAND_RETURN_TIME 300 -#define STEP_TIME 200 -#define DUCK_TIME 100 -#define PAIN_TWITCH_TIME 200 +#define DAMAGE_TIME 500 +#define LAND_DEFLECT_TIME 150 +#define LAND_RETURN_TIME 300 +#define STEP_TIME 200 +#define DUCK_TIME 100 +#define PAIN_TWITCH_TIME 200 #define WEAPON_SELECT_TIME 1400 -#define ITEM_SCALEUP_TIME 1000 -#define ZOOM_TIME 150 -#define ITEM_BLOB_TIME 200 -#define MUZZLE_FLASH_TIME 20 -#define SINK_TIME 1000 // time for fragments to sink into ground before going away +#define ITEM_SCALEUP_TIME 1000 +#define ZOOM_TIME 150 +#define ITEM_BLOB_TIME 200 +#define MUZZLE_FLASH_TIME 20 +#define SINK_TIME 1000 // time for fragments to sink into ground before going away #define ATTACKER_HEAD_TIME 10000 -#define REWARD_TIME 3000 +#define REWARD_TIME 3000 -#define PULSE_SCALE 1.5 // amount to scale up the icons when activating +#define PULSE_SCALE 1.5 // amount to scale up the icons when activating -#define MAX_STEP_CHANGE 32 +#define MAX_STEP_CHANGE 32 -#define MAX_VERTS_ON_POLY 10 -#define MAX_MARK_POLYS 256 +#define MAX_VERTS_ON_POLY 10 +#define MAX_MARK_POLYS 256 -#define STAT_MINUS 10 // num frame for '-' stats digit +#define STAT_MINUS 10 // num frame for '-' stats digit -#define ICON_SIZE 48 -#define CHAR_WIDTH 32 -#define CHAR_HEIGHT 48 -#define TEXT_ICON_SPACE 4 +#define ICON_SIZE 48 +#define CHAR_WIDTH 32 +#define CHAR_HEIGHT 48 +#define TEXT_ICON_SPACE 4 -#define TEAMCHAT_WIDTH 80 -#define TEAMCHAT_HEIGHT 8 +#define TEAMCHAT_WIDTH 80 +#define TEAMCHAT_HEIGHT 8 // very large characters -#define GIANT_WIDTH 32 -#define GIANT_HEIGHT 48 +#define GIANT_WIDTH 32 +#define GIANT_HEIGHT 48 -#define NUM_CROSSHAIRS 10 +#define NUM_CROSSHAIRS 10 #define TEAM_OVERLAY_MAXNAME_WIDTH 12 #define TEAM_OVERLAY_MAXLOCATION_WIDTH 16 -#define DEFAULT_MODEL "sarge" -#define DEFAULT_TEAM_MODEL "sarge" +#define DEFAULT_MODEL "sarge" +#define DEFAULT_TEAM_MODEL "sarge" #define DEFAULT_TEAM_HEAD "sarge" #define DEFAULT_REDTEAM_NAME "Stroggs" @@ -1168,6 +1168,7 @@ extern vmCvar_t cg_bigFont; extern vmCvar_t cg_noTaunt; extern vmCvar_t cg_creepRes; extern vmCvar_t cg_drawSurfNormal; +extern vmCvar_t cg_debugAlloc; // // cg_main.c @@ -1457,9 +1458,17 @@ void CG_TransitionPlayerState( playerState_t *ps, playerState_t *ops ); void CG_CheckChangedPredictableEvents( playerState_t *ps ); // -//cg_mem.c +// cg_mem.c // +void CG_InitMemory( void ); void *CG_Alloc( int size ); +void CG_Free( void *ptr ); +void CG_DefragmentMemory( void ); + +// +// cg_mp3decoder.c +// +qboolean S_decodeMP3( char *mp3File, char *wavFile ); //=============================================== diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c index 926f055c..dfe76d13 100644 --- a/src/cgame/cg_main.c +++ b/src/cgame/cg_main.c @@ -180,6 +180,7 @@ vmCvar_t cg_bigFont; vmCvar_t cg_noTaunt; vmCvar_t cg_creepRes; vmCvar_t cg_drawSurfNormal; +vmCvar_t cg_debugAlloc; typedef struct { @@ -259,6 +260,7 @@ cvarTable_t cvarTable[] = { { &cg_noVoiceText, "cg_noVoiceText", "0", CVAR_ARCHIVE }, { &cg_creepRes, "cg_creepRes", "16", CVAR_ARCHIVE }, { &cg_drawSurfNormal, "cg_drawSurfNormal", "0", CVAR_CHEAT }, + { &cg_debugAlloc, "cg_debugAlloc", "0", 0 }, // the following variables are created in other parts of the system, // but we also reference them here diff --git a/src/cgame/cg_mem.c b/src/cgame/cg_mem.c index 3490edb2..e4ef82ab 100644 --- a/src/cgame/cg_mem.c +++ b/src/cgame/cg_mem.c @@ -1,62 +1,191 @@ // Copyright (C) 1999-2000 Id Software, Inc. // // -// g_mem.c +// cg_mem.c // -//TA: hack to provide dynanmic allocation clientside - -/* - * Portions Copyright (C) 2000-2001 Tim Angus - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1, 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* To assertain which portions are licensed under the LGPL and which are - * licensed by Id Software, Inc. please run a diff between the equivalent - * versions of the "Tremulous" modification and the unmodified "Quake3" - * game source code. - */ - +// Golliwog: All rewritten to allow deallocation +// +// TA: (very) minor changes for client side operation +// thanks to Golliwog of Quake 3 Fortress ( http://www.q3f.com ) +// for this. + + #include "cg_local.h" +#define POOLSIZE (256 * 1024) +#define FREEMEMCOOKIE ((int)0xDEADBE3F) // Any unlikely to be used value +#define ROUNDBITS 31 // Round to 32 bytes + +struct freememnode +{ + // Size of ROUNDBITS + int cookie, size; // Size includes node (obviously) + struct freememnode *prev, *next; +}; -#define POOLSIZE (256 * 1024) +static char memoryPool[ POOLSIZE ]; +static struct freememnode *freehead; +static int freemem; -static char memoryPool[POOLSIZE]; -static int allocPoint; +void *CG_Alloc( int size ) +{ + // Find a free block and allocate. + // Does two passes, attempts to fill same-sized free slot first. -void *CG_Alloc( int size ) { - char *p; + struct freememnode *fmn, *prev, *next, *smallest; + int allocsize, smallestsize; + char *endptr; + int *ptr; - /*if ( g_debugAlloc.integer ) { - G_Printf( "CG_Alloc of %i bytes (%i left)\n", size, POOLSIZE - allocPoint - ( ( size + 31 ) & ~31 ) ); - }*/ + allocsize = ( size + sizeof(int) + ROUNDBITS ) & ~ROUNDBITS; // Round to 32-byte boundary + ptr = NULL; - if ( allocPoint + size > POOLSIZE ) { - CG_Error( "CG_Alloc: failed on allocation of %u bytes\n", size ); - return NULL; + smallest = NULL; + smallestsize = POOLSIZE + 1; // Guaranteed not to miss any slots :) + for( fmn = freehead; fmn; fmn = fmn->next ) + { + if( fmn->cookie != FREEMEMCOOKIE ) + CG_Error( "CG_Alloc: Memory corruption detected!\n" ); + + if( fmn->size >= allocsize ) + { + // We've got a block + if( fmn->size == allocsize ) + { + // Same size, just remove + + prev = fmn->prev; + next = fmn->next; + if( prev ) + prev->next = next; // Point previous node to next + if( next ) + next->prev = prev; // Point next node to previous + if( fmn == freehead ) + freehead = next; // Set head pointer to next + ptr = (int *) fmn; + break; // Stop the loop, this is fine + } + else + { + // Keep track of the smallest free slot + if( fmn->size < smallestsize ) + { + smallest = fmn; + smallestsize = fmn->size; + } + } + } + } + + if( !ptr && smallest ) + { + // We found a slot big enough + smallest->size -= allocsize; + endptr = (char *) smallest + smallest->size; + ptr = (int *) endptr; } - p = &memoryPool[allocPoint]; + if( ptr ) + { + freemem -= allocsize; + if( cg_debugAlloc.integer ) + CG_Printf( "CG_Alloc of %i bytes (%i left)\n", allocsize, freemem ); + memset( ptr, 0, allocsize ); + *ptr++ = allocsize; // Store a copy of size for deallocation + return( (void *) ptr ); + } + + CG_Error( "CG_Alloc: failed on allocation of %i bytes\n", size ); + return( NULL ); +} + +void CG_Free( void *ptr ) +{ + // Release allocated memory, add it to the free list. + + struct freememnode *fmn; + char *freeend; + int *freeptr; + + freeptr = ptr; + freeptr--; - allocPoint += ( size + 31 ) & ~31; + freemem += *freeptr; + if( cg_debugAlloc.integer ) + CG_Printf( "CG_Free of %i bytes (%i left)\n", *freeptr, freemem ); - return p; + for( fmn = freehead; fmn; fmn = fmn->next ) + { + freeend = ((char *) fmn) + fmn->size; + if( freeend == (char *) freeptr ) + { + // Released block can be merged to an existing node + + fmn->size += *freeptr; // Add size of node. + return; + } + } + // No merging, add to head of list + + fmn = (struct freememnode *) freeptr; + fmn->size = *freeptr; // Set this first to avoid corrupting *freeptr + fmn->cookie = FREEMEMCOOKIE; + fmn->prev = NULL; + fmn->next = freehead; + freehead->prev = fmn; + freehead = fmn; } -void CG_InitMemory( void ) { - allocPoint = 0; +void CG_InitMemory( void ) +{ + // Set up the initial node + + freehead = (struct freememnode *) memoryPool; + freehead->cookie = FREEMEMCOOKIE; + freehead->size = POOLSIZE; + freehead->next = NULL; + freehead->prev = NULL; + freemem = sizeof(memoryPool); } +void CG_DefragmentMemory( void ) +{ + // If there's a frenzy of deallocation and we want to + // allocate something big, this is useful. Otherwise... + // not much use. + + struct freememnode *startfmn, *endfmn, *fmn; + + for( startfmn = freehead; startfmn; ) + { + endfmn = (struct freememnode *)(((char *) startfmn) + startfmn->size); + for( fmn = freehead; fmn; ) + { + if( fmn->cookie != FREEMEMCOOKIE ) + CG_Error( "CG_DefragmentMemory: Memory corruption detected!\n" ); + + if( fmn == endfmn ) + { + // We can add fmn onto startfmn. + + if( fmn->prev ) + fmn->prev->next = fmn->next; + if( fmn->next ) + { + if( !(fmn->next->prev = fmn->prev) ) + freehead = fmn->next; // We're removing the head node + } + startfmn->size += fmn->size; + memset( fmn, 0, sizeof(struct freememnode) ); // A redundant call, really. + + startfmn = freehead; + endfmn = fmn = NULL; // Break out of current loop + } + else + fmn = fmn->next; + } + + if( endfmn ) + startfmn = startfmn->next; // endfmn acts as a 'restart' flag here + } +} diff --git a/src/game/bg_public.h b/src/game/bg_public.h index 37a6d367..4e7c3c2b 100644 --- a/src/game/bg_public.h +++ b/src/game/bg_public.h @@ -1022,4 +1022,3 @@ qboolean BG_gotWeapon( int weapon, int stats[ ] );*/ void AxisToAngles( vec3_t axis[3], vec3_t angles); float arccos( float x ); #define Vector2Set(v, x, y) ((v)[0]=(x), (v)[1]=(y)) - diff --git a/src/game/g_local.h b/src/game/g_local.h index e1736309..3c49ab2f 100644 --- a/src/game/g_local.h +++ b/src/game/g_local.h @@ -728,12 +728,13 @@ void G_RunClient( gentity_t *ent ); qboolean OnSameTeam( gentity_t *ent1, gentity_t *ent2 ); void Team_CheckDroppedItem( gentity_t *dropped ); - // // g_mem.c // void *G_Alloc( int size ); void G_InitMemory( void ); +void G_Free( void *ptr ); +void G_DefragmentMemory( void ); void Svcmd_GameMem_f( void ); // diff --git a/src/game/g_mem.c b/src/game/g_mem.c index 9d78e816..1e2dc24a 100644 --- a/src/game/g_mem.c +++ b/src/game/g_mem.c @@ -3,37 +3,203 @@ // // g_mem.c // +// Golliwog: All rewritten to allow deallocation -/* - * Portions Copyright (C) 2000-2001 Tim Angus - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1, 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* To assertain which portions are licensed under the LGPL and which are - * licensed by Id Software, Inc. please run a diff between the equivalent - * versions of the "Tremulous" modification and the unmodified "Quake3" - * game source code. - */ #include "g_local.h" +#define POOLSIZE (256 * 1024) +#define FREEMEMCOOKIE ((int)0xDEADBE3F) // Any unlikely to be used value +#define ROUNDBITS 31 // Round to 32 bytes -#define POOLSIZE (256 * 1024) +struct freememnode +{ + // Size of ROUNDBITS + int cookie, size; // Size includes node (obviously) + struct freememnode *prev, *next; +}; static char memoryPool[POOLSIZE]; +static struct freememnode *freehead; +static int freemem; + +void *G_Alloc( int size ) +{ + // Find a free block and allocate. + // Does two passes, attempts to fill same-sized free slot first. + + struct freememnode *fmn, *prev, *next, *smallest; + int allocsize, smallestsize; + char *endptr; + int *ptr; + + allocsize = ( size + sizeof(int) + ROUNDBITS ) & ~ROUNDBITS; // Round to 32-byte boundary + ptr = NULL; + + smallest = NULL; + smallestsize = POOLSIZE + 1; // Guaranteed not to miss any slots :) + for( fmn = freehead; fmn; fmn = fmn->next ) + { + if( fmn->cookie != FREEMEMCOOKIE ) + G_Error( "G_Alloc: Memory corruption detected!\n" ); + + if( fmn->size >= allocsize ) + { + // We've got a block + if( fmn->size == allocsize ) + { + // Same size, just remove + + prev = fmn->prev; + next = fmn->next; + if( prev ) + prev->next = next; // Point previous node to next + if( next ) + next->prev = prev; // Point next node to previous + if( fmn == freehead ) + freehead = next; // Set head pointer to next + ptr = (int *) fmn; + break; // Stop the loop, this is fine + } + else + { + // Keep track of the smallest free slot + if( fmn->size < smallestsize ) + { + smallest = fmn; + smallestsize = fmn->size; + } + } + } + } + + if( !ptr && smallest ) + { + // We found a slot big enough + smallest->size -= allocsize; + endptr = (char *) smallest + smallest->size; + ptr = (int *) endptr; + } + + if( ptr ) + { + freemem -= allocsize; + if( g_debugAlloc.integer ) + G_Printf( "G_Alloc of %i bytes (%i left)\n", allocsize, freemem ); + memset( ptr, 0, allocsize ); + *ptr++ = allocsize; // Store a copy of size for deallocation + return( (void *) ptr ); + } + + G_Error( "G_Alloc: failed on allocation of %i bytes\n", size ); + return( NULL ); +} + +void G_Free( void *ptr ) +{ + // Release allocated memory, add it to the free list. + + struct freememnode *fmn; + char *freeend; + int *freeptr; + + freeptr = ptr; + freeptr--; + + freemem += *freeptr; + if( g_debugAlloc.integer ) + G_Printf( "G_Free of %i bytes (%i left)\n", *freeptr, freemem ); + + for( fmn = freehead; fmn; fmn = fmn->next ) + { + freeend = ((char *) fmn) + fmn->size; + if( freeend == (char *) freeptr ) + { + // Released block can be merged to an existing node + + fmn->size += *freeptr; // Add size of node. + return; + } + } + // No merging, add to head of list + + fmn = (struct freememnode *) freeptr; + fmn->size = *freeptr; // Set this first to avoid corrupting *freeptr + fmn->cookie = FREEMEMCOOKIE; + fmn->prev = NULL; + fmn->next = freehead; + freehead->prev = fmn; + freehead = fmn; +} + +void G_InitMemory( void ) +{ + // Set up the initial node + + freehead = (struct freememnode *) memoryPool; + freehead->cookie = FREEMEMCOOKIE; + freehead->size = POOLSIZE; + freehead->next = NULL; + freehead->prev = NULL; + freemem = sizeof(memoryPool); +} + +void G_DefragmentMemory( void ) +{ + // If there's a frenzy of deallocation and we want to + // allocate something big, this is useful. Otherwise... + // not much use. + + struct freememnode *startfmn, *endfmn, *fmn; + + for( startfmn = freehead; startfmn; ) + { + endfmn = (struct freememnode *)(((char *) startfmn) + startfmn->size); + for( fmn = freehead; fmn; ) + { + if( fmn->cookie != FREEMEMCOOKIE ) + G_Error( "G_DefragmentMemory: Memory corruption detected!\n" ); + + if( fmn == endfmn ) + { + // We can add fmn onto startfmn. + + if( fmn->prev ) + fmn->prev->next = fmn->next; + if( fmn->next ) + { + if( !(fmn->next->prev = fmn->prev) ) + freehead = fmn->next; // We're removing the head node + } + startfmn->size += fmn->size; + memset( fmn, 0, sizeof(struct freememnode) ); // A redundant call, really. + + startfmn = freehead; + endfmn = fmn = NULL; // Break out of current loop + } + else + fmn = fmn->next; + } + + if( endfmn ) + startfmn = startfmn->next; // endfmn acts as a 'restart' flag here + } +} + +void Svcmd_GameMem_f( void ) +{ + // Give a breakdown of memory + + struct freememnode *fmn; + + G_Printf( "Game memory status: %i out of %i bytes allocated\n", POOLSIZE - freemem, POOLSIZE ); + + for( fmn = freehead; fmn; fmn = fmn->next ) + G_Printf( " %dd: %d bytes free.\n", fmn, fmn->size ); + G_Printf( "Status complete.\n" ); +} + +/* Golliwog: All rewritten static int allocPoint; void *G_Alloc( int size ) { @@ -44,7 +210,7 @@ void *G_Alloc( int size ) { } if ( allocPoint + size > POOLSIZE ) { - G_Error( "G_Alloc: failed on allocation of %u bytes\n", size ); + G_Error( "G_Alloc: failed on allocation of %i bytes\n", size ); return NULL; } @@ -62,3 +228,5 @@ void G_InitMemory( void ) { void Svcmd_GameMem_f( void ) { G_Printf( "Game memory status: %i out of %i bytes allocated\n", allocPoint, POOLSIZE ); } +// Golliwog. +*/ diff --git a/src/game/q_shared.h b/src/game/q_shared.h index 895f1961..6faaced2 100644 --- a/src/game/q_shared.h +++ b/src/game/q_shared.h @@ -366,6 +366,11 @@ typedef int fixed16_t; #define M_PI 3.14159265358979323846f // matches value in gcc v2 math.h #endif +//TA: stop telling others not to edit q_* <:) +#ifndef M_SQRT2 +#define M_SQRT2 1.414213562f +#endif + #define NUMVERTEXNORMALS 162 extern vec3_t bytedirs[NUMVERTEXNORMALS]; |