diff options
| -rwxr-xr-x | misc/merge-ioq3-into-trem.sh | 2 | ||||
| -rw-r--r-- | src/client/cl_avi.c | 619 | ||||
| -rw-r--r-- | src/client/cl_main.c | 143 | ||||
| -rw-r--r-- | src/client/client.h | 12 | ||||
| -rw-r--r-- | src/client/snd_dma.c | 6 | ||||
| -rw-r--r-- | src/client/snd_main.c | 4 | ||||
| -rw-r--r-- | src/client/snd_mix.c | 4 | ||||
| -rw-r--r-- | src/qcommon/common.c | 310 | ||||
| -rw-r--r-- | src/qcommon/files.c | 92 | ||||
| -rw-r--r-- | src/qcommon/md4.c | 5 | ||||
| -rw-r--r-- | src/qcommon/q_shared.h | 5 | ||||
| -rw-r--r-- | src/qcommon/qcommon.h | 4 | ||||
| -rw-r--r-- | src/renderer/tr_backend.c | 3 | ||||
| -rw-r--r-- | src/renderer/tr_cmds.c | 27 | ||||
| -rw-r--r-- | src/renderer/tr_image.c | 58 | ||||
| -rw-r--r-- | src/renderer/tr_init.c | 47 | ||||
| -rw-r--r-- | src/renderer/tr_local.h | 18 | ||||
| -rw-r--r-- | src/renderer/tr_public.h | 3 | ||||
| -rw-r--r-- | src/unix/Makefile | 360 | ||||
| -rw-r--r-- | src/unix/ftola.s | 2 | ||||
| -rw-r--r-- | src/unix/linux_common.c | 347 | 
21 files changed, 1034 insertions, 1037 deletions
diff --git a/misc/merge-ioq3-into-trem.sh b/misc/merge-ioq3-into-trem.sh index 416d6dcb..2e4add43 100755 --- a/misc/merge-ioq3-into-trem.sh +++ b/misc/merge-ioq3-into-trem.sh @@ -31,7 +31,7 @@ rm -f `find -iname "*.def"`  rm -f `find -iname "*.q3asm"`  rm -f `find -iname "*.mak"`  rm -f code/tools/lcc/makefile.nt -rm -f code/win32/msvc/ +rm -rf code/win32/msvc/  # Remove Linux docs  rm -rf code/unix/LinuxSupport/ diff --git a/src/client/cl_avi.c b/src/client/cl_avi.c new file mode 100644 index 00000000..4a372d8b --- /dev/null +++ b/src/client/cl_avi.c @@ -0,0 +1,619 @@ +/* +=========================================================================== +Copyright (C) 2005-2006 Tim Angus + +This file is part of Quake III Arena source code. + +Quake III Arena source code 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 2 of the License, +or (at your option) any later version. + +Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ + +#include "client.h" +#include "snd_local.h" + +#define MAX_RIFF_CHUNKS 16 + +typedef struct audioFormat_s +{ +  int rate; +  int format; +  int channels; +  int bits; + +  int sampleSize; +  int totalBytes; +} audioFormat_t; + +typedef struct aviFileData_s +{ +  qboolean      fileOpen; +  fileHandle_t  f; +  char          fileName[ MAX_QPATH ]; +  int           fileSize; +  int           moviOffset; +  int           moviSize; + +  fileHandle_t  idxF; +  int           numIndices; + +  int           frameRate; +  int           framePeriod; +  int           width, height; +  int           numVideoFrames; +  int           maxRecordSize; +  qboolean      motionJpeg; + +  qboolean      audio; +  audioFormat_t a; +  int           numAudioFrames; + +  int           chunkStack[ MAX_RIFF_CHUNKS ]; +  int           chunkStackTop; + +  byte          *cBuffer, *eBuffer; +} aviFileData_t; + +static aviFileData_t afd; + +#define MAX_AVI_BUFFER 2048 + +static byte buffer[ MAX_AVI_BUFFER ]; +static int  bufIndex; + +/* +=============== +SafeFS_Write +=============== +*/ +static ID_INLINE void SafeFS_Write( const void *buffer, int len, fileHandle_t f ) +{ +  if( FS_Write( buffer, len, f ) < len ) +    Com_Error( ERR_DROP, "Failed to write avi file\n" ); +} + +/* +=============== +WRITE_STRING +=============== +*/ +static ID_INLINE void WRITE_STRING( const char *s ) +{ +  Com_Memcpy( &buffer[ bufIndex ], s, strlen( s ) ); +  bufIndex += strlen( s ); +} + +/* +=============== +WRITE_4BYTES +=============== +*/ +static ID_INLINE void WRITE_4BYTES( int x ) +{ +  buffer[ bufIndex + 0 ] = (byte)( ( x >>  0 ) & 0xFF ); +  buffer[ bufIndex + 1 ] = (byte)( ( x >>  8 ) & 0xFF ); +  buffer[ bufIndex + 2 ] = (byte)( ( x >> 16 ) & 0xFF ); +  buffer[ bufIndex + 3 ] = (byte)( ( x >> 24 ) & 0xFF ); +  bufIndex += 4; +} + +/* +=============== +WRITE_2BYTES +=============== +*/ +static ID_INLINE void WRITE_2BYTES( int x ) +{ +  buffer[ bufIndex + 0 ] = (byte)( ( x >>  0 ) & 0xFF ); +  buffer[ bufIndex + 1 ] = (byte)( ( x >>  8 ) & 0xFF ); +  bufIndex += 2; +} + +/* +=============== +WRITE_1BYTES +=============== +*/ +static ID_INLINE void WRITE_1BYTES( int x ) +{ +  buffer[ bufIndex ] = x; +  bufIndex += 1; +} + +/* +=============== +START_CHUNK +=============== +*/ +static ID_INLINE void START_CHUNK( const char *s ) +{ +  if( afd.chunkStackTop == MAX_RIFF_CHUNKS ) +  { +    Com_Error( ERR_DROP, "ERROR: Top of chunkstack breached\n" ); +  } + +  afd.chunkStack[ afd.chunkStackTop ] = bufIndex; +  afd.chunkStackTop++; +  WRITE_STRING( s ); +  WRITE_4BYTES( 0 ); +} + +/* +=============== +END_CHUNK +=============== +*/ +static ID_INLINE void END_CHUNK( void ) +{ +  int endIndex = bufIndex; + +  if( afd.chunkStackTop <= 0 ) +  { +    Com_Error( ERR_DROP, "ERROR: Bottom of chunkstack breached\n" ); +  } + +  afd.chunkStackTop--; +  bufIndex = afd.chunkStack[ afd.chunkStackTop ]; +  bufIndex += 4; +  WRITE_4BYTES( endIndex - bufIndex - 1 ); +  bufIndex = endIndex; +  bufIndex = PAD( bufIndex, 2 ); +} + +/* +=============== +CL_WriteAVIHeader +=============== +*/ +void CL_WriteAVIHeader( void ) +{ +  bufIndex = 0; +  afd.chunkStackTop = 0; + +  START_CHUNK( "RIFF" ); +  { +    WRITE_STRING( "AVI " ); +    { +      START_CHUNK( "LIST" ); +      { +        WRITE_STRING( "hdrl" ); +        WRITE_STRING( "avih" ); +        WRITE_4BYTES( 56 );                     //"avih" "chunk" size +        WRITE_4BYTES( afd.framePeriod );        //dwMicroSecPerFrame +        WRITE_4BYTES( afd.maxRecordSize * +            afd.frameRate );                    //dwMaxBytesPerSec +        WRITE_4BYTES( 0 );                      //dwReserved1 +        WRITE_4BYTES( 0x110 );                  //dwFlags bits HAS_INDEX and IS_INTERLEAVED +        WRITE_4BYTES( afd.numVideoFrames );     //dwTotalFrames +        WRITE_4BYTES( 0 );                      //dwInitialFrame + +        if( afd.audio )                         //dwStreams +          WRITE_4BYTES( 2 ); +        else +          WRITE_4BYTES( 1 ); + +        WRITE_4BYTES( afd.maxRecordSize );      //dwSuggestedBufferSize +        WRITE_4BYTES( afd.width );              //dwWidth +        WRITE_4BYTES( afd.height );             //dwHeight +        WRITE_4BYTES( 0 );                      //dwReserved[ 0 ] +        WRITE_4BYTES( 0 );                      //dwReserved[ 1 ] +        WRITE_4BYTES( 0 );                      //dwReserved[ 2 ] +        WRITE_4BYTES( 0 );                      //dwReserved[ 3 ] + +        START_CHUNK( "LIST" ); +        { +          WRITE_STRING( "strl" ); +          WRITE_STRING( "strh" ); +          WRITE_4BYTES( 56 );                   //"strh" "chunk" size +          WRITE_STRING( "vids" ); + +          if( afd.motionJpeg ) +            WRITE_STRING( "MJPG" ); +          else +            WRITE_STRING( " BGR" ); + +          WRITE_4BYTES( 0 );                    //dwFlags +          WRITE_4BYTES( 0 );                    //dwPriority +          WRITE_4BYTES( 0 );                    //dwInitialFrame + +          WRITE_4BYTES( 1 );                    //dwTimescale +          WRITE_4BYTES( afd.frameRate );        //dwDataRate +          WRITE_4BYTES( 0 );                    //dwStartTime +          WRITE_4BYTES( afd.numVideoFrames );   //dwDataLength + +          WRITE_4BYTES( afd.maxRecordSize );    //dwSuggestedBufferSize +          WRITE_4BYTES( -1 );                   //dwQuality +          WRITE_4BYTES( 0 );                    //dwSampleSize +          WRITE_2BYTES( 0 );                    //rcFrame +          WRITE_2BYTES( 0 );                    //rcFrame +          WRITE_2BYTES( afd.width );            //rcFrame +          WRITE_2BYTES( afd.height );           //rcFrame + +          WRITE_STRING( "strf" ); +          WRITE_4BYTES( 40 );                   //"strf" "chunk" size +          WRITE_4BYTES( 40 );                   //biSize +          WRITE_4BYTES( afd.width );            //biWidth +          WRITE_4BYTES( afd.height );           //biHeight +          WRITE_2BYTES( 1 );                    //biPlanes +          WRITE_2BYTES( 24 );                   //biBitCount + +          if( afd.motionJpeg )                        //biCompression +            WRITE_STRING( "MJPG" ); +          else +            WRITE_STRING( " BGR" ); + +          WRITE_4BYTES( afd.width * +              afd.height );                     //biSizeImage +          WRITE_4BYTES( 0 );                    //biXPelsPetMeter +          WRITE_4BYTES( 0 );                    //biYPelsPetMeter +          WRITE_4BYTES( 0 );                    //biClrUsed +          WRITE_4BYTES( 0 );                    //biClrImportant +        } +        END_CHUNK( ); + +        if( afd.audio ) +        { +          START_CHUNK( "LIST" ); +          { +            WRITE_STRING( "strl" ); +            WRITE_STRING( "strh" ); +            WRITE_4BYTES( 56 );                 //"strh" "chunk" size +            WRITE_STRING( "auds" ); +            WRITE_4BYTES( 0 );                  //FCC +            WRITE_4BYTES( 0 );                  //dwFlags +            WRITE_4BYTES( 0 );                  //dwPriority +            WRITE_4BYTES( 0 );                  //dwInitialFrame + +            WRITE_4BYTES( afd.a.sampleSize );   //dwTimescale +            WRITE_4BYTES( afd.a.sampleSize * +                afd.a.rate );                   //dwDataRate +            WRITE_4BYTES( 0 );                  //dwStartTime +            WRITE_4BYTES( afd.a.totalBytes / +                afd.a.sampleSize );             //dwDataLength + +            WRITE_4BYTES( 0 );                  //dwSuggestedBufferSize +            WRITE_4BYTES( -1 );                 //dwQuality +            WRITE_4BYTES( afd.a.sampleSize );   //dwSampleSize +            WRITE_2BYTES( 0 );                  //rcFrame +            WRITE_2BYTES( 0 );                  //rcFrame +            WRITE_2BYTES( 0 );                  //rcFrame +            WRITE_2BYTES( 0 );                  //rcFrame + +            WRITE_STRING( "strf" ); +            WRITE_4BYTES( 18 );                 //"strf" "chunk" size +            WRITE_2BYTES( afd.a.format );       //wFormatTag +            WRITE_2BYTES( afd.a.channels );     //nChannels +            WRITE_4BYTES( afd.a.rate );         //nSamplesPerSec +            WRITE_4BYTES( afd.a.sampleSize * +                afd.a.rate );                   //nAvgBytesPerSec +            WRITE_2BYTES( afd.a.sampleSize );   //nBlockAlign +            WRITE_2BYTES( afd.a.bits );         //wBitsPerSample +            WRITE_2BYTES( 0 );                  //cbSize +          } +          END_CHUNK( ); +        } +      } +      END_CHUNK( ); + +      afd.moviOffset = bufIndex; + +      START_CHUNK( "LIST" ); +      { +        WRITE_STRING( "movi" ); +      } +    } +  } +} + +/* +=============== +CL_OpenAVIForWriting + +Creates an AVI file and gets it into a state where +writing the actual data can begin +=============== +*/ +qboolean CL_OpenAVIForWriting( const char *fileName ) +{ +  if( afd.fileOpen ) +    return qfalse; + +  Com_Memset( &afd, 0, sizeof( aviFileData_t ) ); + +  // Don't start if a framerate has not been chosen +  if( cl_avidemo->integer <= 0 ) +  { +    Com_Printf( S_COLOR_RED "cl_avidemo must be >= 1\n" ); +    return qfalse; +  } + +  if( ( afd.f = FS_FOpenFileWrite( fileName ) ) <= 0 ) +    return qfalse; + +  if( ( afd.idxF = FS_FOpenFileWrite( va( "%s.idx", fileName ) ) ) <= 0 ) +  { +    FS_FCloseFile( afd.f ); +    return qfalse; +  } + +  Q_strncpyz( afd.fileName, fileName, MAX_QPATH ); + +  afd.frameRate = cl_avidemo->integer; +  afd.framePeriod = (int)( 1000000.0f / afd.frameRate ); +  afd.width = cls.glconfig.vidWidth; +  afd.height = cls.glconfig.vidHeight; + +  if( cl_aviMotionJpeg->integer ) +    afd.motionJpeg = qtrue; +  else +    afd.motionJpeg = qfalse; + +  afd.cBuffer = Z_Malloc( afd.width * afd.height * 4 ); +  afd.eBuffer = Z_Malloc( afd.width * afd.height * 4 ); + +  afd.a.rate = dma.speed; +  afd.a.format = WAV_FORMAT_PCM; +  afd.a.channels = dma.channels; +  afd.a.bits = dma.samplebits; +  afd.a.sampleSize = ( afd.a.bits / 8 ) * afd.a.channels; + +  if( afd.a.rate % afd.frameRate ) +  { +    int suggestRate = afd.frameRate; + +    while( ( afd.a.rate % suggestRate ) && suggestRate >= 1 ) +      suggestRate--; + +    Com_Printf( S_COLOR_YELLOW "WARNING: cl_avidemo is not a divisor " +        "of the audio rate, suggest %d\n", suggestRate ); +  } + +  if( !Cvar_VariableIntegerValue( "s_initsound" ) ) +  { +    afd.audio = qfalse; +  } +  else if( Q_stricmp( Cvar_VariableString( "s_backend" ), "OpenAL" ) ) +  { +    if( afd.a.bits == 16 && afd.a.channels == 2 ) +      afd.audio = qtrue; +    else +      afd.audio = qfalse; //FIXME: audio not implemented for this case +  } +  else +  { +    afd.audio = qfalse; +    Com_Printf( S_COLOR_YELLOW "WARNING: Audio capture is not supported " +        "with OpenAL. Set s_useOpenAL to 0 for audio capture\n" ); +  } + +  // This doesn't write a real header, but allocates the +  // correct amount of space at the beginning of the file +  CL_WriteAVIHeader( ); + +  SafeFS_Write( buffer, bufIndex, afd.f ); +  afd.fileSize = bufIndex; + +  bufIndex = 0; +  START_CHUNK( "idx1" ); +  SafeFS_Write( buffer, bufIndex, afd.idxF ); + +  afd.moviSize = 4; // For the "movi" +  afd.fileOpen = qtrue; + +  return qtrue; +} + +/* +=============== +CL_WriteAVIVideoFrame +=============== +*/ +void CL_WriteAVIVideoFrame( const byte *imageBuffer, int size ) +{ +  int   chunkOffset = afd.fileSize - afd.moviOffset - 8; +  int   chunkSize = 8 + size; +  int   paddingSize = PAD( size, 2 ) - size; +  byte  padding[ 4 ] = { 0 }; + +  if( !afd.fileOpen ) +    return; + +  bufIndex = 0; +  WRITE_STRING( "00dc" ); +  WRITE_4BYTES( size ); + +  SafeFS_Write( buffer, 8, afd.f ); +  SafeFS_Write( imageBuffer, size, afd.f ); +  SafeFS_Write( padding, paddingSize, afd.f ); +  afd.fileSize += ( chunkSize + paddingSize ); + +  afd.numVideoFrames++; +  afd.moviSize += ( chunkSize + paddingSize ); + +  if( size > afd.maxRecordSize ) +    afd.maxRecordSize = size; + +  // Index +  bufIndex = 0; +  WRITE_STRING( "00dc" );           //dwIdentifier +  WRITE_4BYTES( 0 );                //dwFlags +  WRITE_4BYTES( chunkOffset );      //dwOffset +  WRITE_4BYTES( size );             //dwLength +  SafeFS_Write( buffer, 16, afd.idxF ); + +  afd.numIndices++; +} + +#define PCM_BUFFER_SIZE 44100 + +/* +=============== +CL_WriteAVIAudioFrame +=============== +*/ +void CL_WriteAVIAudioFrame( const byte *pcmBuffer, int size ) +{ +  static byte pcmCaptureBuffer[ PCM_BUFFER_SIZE ] = { 0 }; +  static int  bytesInBuffer = 0; + +  if( !afd.audio ) +    return; + +  if( !afd.fileOpen ) +    return; + +  if( bytesInBuffer + size > PCM_BUFFER_SIZE ) +  { +    Com_Printf( S_COLOR_YELLOW +        "WARNING: Audio capture buffer overflow -- truncating\n" ); +    size = PCM_BUFFER_SIZE - bytesInBuffer; +  } + +  Com_Memcpy( &pcmCaptureBuffer[ bytesInBuffer ], pcmBuffer, size ); +  bytesInBuffer += size; + +  // Only write if we have a frame's worth of audio +  if( bytesInBuffer >= (int)ceil( afd.a.rate / cl_avidemo->value ) * +        afd.a.sampleSize ) +  { +    int   chunkOffset = afd.fileSize - afd.moviOffset - 8; +    int   chunkSize = 8 + bytesInBuffer; +    int   paddingSize = PAD( bytesInBuffer, 2 ) - bytesInBuffer; +    byte  padding[ 4 ] = { 0 }; + +    bufIndex = 0; +    WRITE_STRING( "01wb" ); +    WRITE_4BYTES( bytesInBuffer ); + +    SafeFS_Write( buffer, 8, afd.f ); +    SafeFS_Write( pcmBuffer, bytesInBuffer, afd.f ); +    SafeFS_Write( padding, paddingSize, afd.f ); +    afd.fileSize += ( chunkSize + paddingSize ); + +    afd.numAudioFrames++; +    afd.moviSize += ( chunkSize + paddingSize ); +    afd.a.totalBytes =+ bytesInBuffer; + +    // Index +    bufIndex = 0; +    WRITE_STRING( "01wb" );           //dwIdentifier +    WRITE_4BYTES( 0 );                //dwFlags +    WRITE_4BYTES( chunkOffset );      //dwOffset +    WRITE_4BYTES( bytesInBuffer );    //dwLength +    SafeFS_Write( buffer, 16, afd.idxF ); + +    afd.numIndices++; + +    bytesInBuffer = 0; +  } +} + +/* +=============== +CL_TakeVideoFrame +=============== +*/ +void CL_TakeVideoFrame( void ) +{ +  // AVI file isn't open +  if( !afd.fileOpen ) +    return; + +  re.TakeVideoFrame( afd.width, afd.height, +      afd.cBuffer, afd.eBuffer, afd.motionJpeg ); +} + +/* +=============== +CL_CloseAVI + +Closes the AVI file and writes an index chunk +=============== +*/ +qboolean CL_CloseAVI( void ) +{ +  int indexRemainder; +  int indexSize = afd.numIndices * 16; +  const char *idxFileName = va( "%s.idx", afd.fileName ); + +  // AVI file isn't open +  if( !afd.fileOpen ) +    return qfalse; + +  afd.fileOpen = qfalse; + +  FS_Seek( afd.idxF, 4, FS_SEEK_SET ); +  bufIndex = 0; +  WRITE_4BYTES( indexSize ); +  SafeFS_Write( buffer, bufIndex, afd.idxF ); +  FS_FCloseFile( afd.idxF ); + +  // Write index + +  // Open the temp index file +  if( ( indexSize = FS_FOpenFileRead( idxFileName, +          &afd.idxF, qtrue ) ) <= 0 ) +  { +    FS_FCloseFile( afd.f ); +    return qfalse; +  } + +  indexRemainder = indexSize; + +  // Append index to end of avi file +  while( indexRemainder > MAX_AVI_BUFFER ) +  { +    FS_Read( buffer, MAX_AVI_BUFFER, afd.idxF ); +    SafeFS_Write( buffer, MAX_AVI_BUFFER, afd.f ); +    afd.fileSize += MAX_AVI_BUFFER; +    indexRemainder -= MAX_AVI_BUFFER; +  } +  FS_Read( buffer, indexRemainder, afd.idxF ); +  SafeFS_Write( buffer, indexRemainder, afd.f ); +  afd.fileSize += indexRemainder; +  FS_FCloseFile( afd.idxF ); + +  // Remove temp index file +  FS_HomeRemove( idxFileName ); + +  // Write the real header +  FS_Seek( afd.f, 0, FS_SEEK_SET ); +  CL_WriteAVIHeader( ); + +  bufIndex = 4; +  WRITE_4BYTES( afd.fileSize - 8 ); // "RIFF" size + +  bufIndex = afd.moviOffset + 4;    // Skip "LIST" +  WRITE_4BYTES( afd.moviSize ); + +  SafeFS_Write( buffer, bufIndex, afd.f ); + +  Z_Free( afd.cBuffer ); +  Z_Free( afd.eBuffer ); +  FS_FCloseFile( afd.f ); + +  Com_Printf( "Wrote %d:%d frames to %s\n", afd.numVideoFrames, afd.numAudioFrames, afd.fileName ); + +  return qtrue; +} + +/* +=============== +CL_VideoRecording +=============== +*/ +qboolean CL_VideoRecording( void ) +{ +  return afd.fileOpen; +} diff --git a/src/client/cl_main.c b/src/client/cl_main.c index 0789ac9b..04d87cc1 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -44,7 +44,9 @@ cvar_t	*cl_freezeDemo;  cvar_t	*cl_shownet;  cvar_t	*cl_showSend;  cvar_t	*cl_timedemo; +cvar_t	*cl_autoRecordDemo;  cvar_t	*cl_avidemo; +cvar_t	*cl_aviMotionJpeg;  cvar_t	*cl_forceavidemo;  cvar_t	*cl_freelook; @@ -283,7 +285,7 @@ void CL_Record_f( void ) {  	}    // sync 0 doesn't prevent recording, so not forcing it off .. everyone does g_sync 1 ; record ; g_sync 0 .. -	if ( !Cvar_VariableValue( "g_synchronousClients" ) ) { +	if ( NET_IsLocalAddress( clc.serverAddress ) && !Cvar_VariableValue( "g_synchronousClients" ) ) {  		Com_Printf (S_COLOR_YELLOW "WARNING: You should set 'g_synchronousClients 1' for smoother demo recording\n");  	} @@ -774,6 +776,11 @@ void CL_Disconnect( qboolean showMainMenu ) {  	// not connected to a pure server anymore  	cl_connectedToPureServer = qfalse; + +	// Stop recording any video +	if( CL_VideoRecording( ) ) { +		CL_CloseAVI( ); +	}  } @@ -1105,6 +1112,11 @@ doesn't know what graphics to reload  */  void CL_Vid_Restart_f( void ) { +	// Settings may have changed so stop recording now +	if( CL_VideoRecording( ) ) { +		CL_CloseAVI( ); +	} +  	// don't let them loop during the restart  	S_StopAllSounds();  	// shutdown the UI @@ -1916,18 +1928,57 @@ void CL_Frame ( int msec ) {  	}  	// if recording an avi, lock to a fixed fps -	if ( cl_avidemo->integer && msec) { +	if ( CL_VideoRecording( ) && cl_avidemo->integer && msec) {  		// save the current screen  		if ( cls.state == CA_ACTIVE || cl_forceavidemo->integer) { -			Cbuf_ExecuteText( EXEC_NOW, "screenshot silent\n" ); -		} -		// fixed time for next frame' -		msec = (1000 / cl_avidemo->integer) * com_timescale->value; -		if (msec == 0) { -			msec = 1; +			CL_TakeVideoFrame( ); + +			// fixed time for next frame' +			msec = (int)ceil( (1000.0f / cl_avidemo->value) * com_timescale->value ); +			if (msec == 0) { +				msec = 1; +			}  		}  	} +	if( cl_autoRecordDemo->integer ) { +		if( cls.state == CA_ACTIVE && !clc.demorecording ) { +			// If not recording a demo, and we should be, start one +			qtime_t	now; +			char		*nowString; +			char		*p; +			char		mapName[ MAX_QPATH ]; +			char		serverName[ MAX_OSPATH ]; + +			Com_RealTime( &now ); +			nowString = va( "%04d%02d%02d%02d%02d%02d", +					1900 + now.tm_year, +					1 + now.tm_mon, +					now.tm_mday, +					now.tm_hour, +					now.tm_min, +					now.tm_sec ); + +			Q_strncpyz( serverName, cls.servername, MAX_OSPATH ); +			// Replace the ":" in the address as it is not a valid +			// file name character +			p = strstr( serverName, ":" ); +			if( p ) { +				*p = '.'; +			} + +			Q_strncpyz( mapName, COM_SkipPath( cl.mapname ), sizeof( cl.mapname ) ); +			COM_StripExtension( mapName, mapName ); + +			Cbuf_ExecuteText( EXEC_NOW, +					va( "record %s-%s-%s", nowString, serverName, mapName ) ); +		} +		else if( cls.state != CA_ACTIVE && clc.demorecording ) { +			// Recording, but not CA_ACTIVE, so stop recording +			CL_StopRecord_f( ); +		} +	} +  	// save the msec before checking pause  	cls.realFrametime = msec; @@ -2124,6 +2175,8 @@ void CL_InitRef( void ) {  	ri.CIN_UploadCinematic = CIN_UploadCinematic;  	ri.CIN_PlayCinematic = CIN_PlayCinematic;  	ri.CIN_RunCinematic = CIN_RunCinematic; +   +	ri.CL_WriteAVIVideoFrame = CL_WriteAVIVideoFrame;  	ret = GetRefAPI( REF_API_VERSION, &ri ); @@ -2161,6 +2214,72 @@ void CL_SetModel_f( void ) {  	}  } + +//=========================================================================================== + + +/* +=============== +CL_Video_f + +video +video [filename] +=============== +*/ +void CL_Video_f( void ) +{ +  char  filename[ MAX_OSPATH ]; +  int   i, last; + +  if( Cmd_Argc( ) == 2 ) +  { +    // explicit filename +    Com_sprintf( filename, MAX_OSPATH, "videos/%s.avi", Cmd_Argv( 1 ) ); +  } +  else +  { +    // scan for a free filename +    for( i = 0; i <= 9999; i++ ) +    { +      int a, b, c, d; + +      last = i; + +      a = last / 1000; +      last -= a * 1000; +      b = last / 100; +      last -= b * 100; +      c = last / 10; +      last -= c * 10; +      d = last; + +      Com_sprintf( filename, MAX_OSPATH, "videos/video%d%d%d%d.avi", +          a, b, c, d ); + +      if( !FS_FileExists( filename ) ) +        break; // file doesn't exist +    } + +    if( i > 9999 ) +    { +      Com_Printf( S_COLOR_RED "ERROR: no free file names to create video\n" ); +      return; +    } +  } + +  CL_OpenAVIForWriting( filename ); +} + +/* +=============== +CL_StopVideo_f +=============== +*/ +void CL_StopVideo_f( void ) +{ +  CL_CloseAVI( ); +} +  /*  ====================  CL_Init @@ -2196,7 +2315,9 @@ void CL_Init( void ) {  	cl_activeAction = Cvar_Get( "activeAction", "", CVAR_TEMP );  	cl_timedemo = Cvar_Get ("timedemo", "0", 0); -	cl_avidemo = Cvar_Get ("cl_avidemo", "0", 0); +	cl_autoRecordDemo = Cvar_Get ("cl_autoRecordDemo", "0", CVAR_ARCHIVE); +	cl_avidemo = Cvar_Get ("cl_avidemo", "25", CVAR_ARCHIVE); +	cl_aviMotionJpeg = Cvar_Get ("cl_aviMotionJpeg", "1", CVAR_ARCHIVE);  	cl_forceavidemo = Cvar_Get ("cl_forceavidemo", "0", 0);  	rconAddress = Cvar_Get ("rconAddress", "", 0); @@ -2297,6 +2418,8 @@ void CL_Init( void ) {  	Cmd_AddCommand ("fs_openedList", CL_OpenedPK3List_f );  	Cmd_AddCommand ("fs_referencedList", CL_ReferencedPK3List_f );  	Cmd_AddCommand ("model", CL_SetModel_f ); +	Cmd_AddCommand ("video", CL_Video_f ); +	Cmd_AddCommand ("stopvideo", CL_StopVideo_f );  	CL_InitRef();  	SCR_Init (); @@ -2352,6 +2475,8 @@ void CL_Shutdown( void ) {  	Cmd_RemoveCommand ("serverstatus");  	Cmd_RemoveCommand ("showip");  	Cmd_RemoveCommand ("model"); +	Cmd_RemoveCommand ("video"); +	Cmd_RemoveCommand ("stopvideo");  	Cvar_Set( "cl_running", "0" ); diff --git a/src/client/client.h b/src/client/client.h index e597047f..5f609dde 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -343,6 +343,8 @@ extern	cvar_t	*m_side;  extern	cvar_t	*m_filter;  extern	cvar_t	*cl_timedemo; +extern	cvar_t	*cl_avidemo; +extern	cvar_t	*cl_aviMotionJpeg;  extern	cvar_t	*cl_activeAction; @@ -518,3 +520,13 @@ void LAN_SaveServersToCache( void );  void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg);	//int length, const byte *data );  void CL_Netchan_TransmitNextFragment( netchan_t *chan );  qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ); + +// +// cl_avi.c +// +qboolean CL_OpenAVIForWriting( const char *filename ); +void CL_TakeVideoFrame( void ); +void CL_WriteAVIVideoFrame( const byte *imageBuffer, int size ); +void CL_WriteAVIAudioFrame( const byte *pcmBuffer, int size ); +qboolean CL_CloseAVI( void ); +qboolean CL_VideoRecording( void ); diff --git a/src/client/snd_dma.c b/src/client/snd_dma.c index 6860179f..d51a4b85 100644 --- a/src/client/snd_dma.c +++ b/src/client/snd_dma.c @@ -1140,6 +1140,12 @@ void S_GetSoundtime(void)  	fullsamples = dma.samples / dma.channels; +	if( CL_VideoRecording( ) ) +	{ +		s_soundtime += (int)ceil( dma.speed / cl_avidemo->value ); +		return; +	} +  	// it is possible to miscount buffers if it has wrapped twice between  	// calls to S_Update.  Oh well.  	samplepos = SNDDMA_GetDMAPos(); diff --git a/src/client/snd_main.c b/src/client/snd_main.c index d83996a8..1ecdc237 100644 --- a/src/client/snd_main.c +++ b/src/client/snd_main.c @@ -30,6 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  cvar_t *s_volume;  cvar_t *s_musicVolume;  cvar_t *s_doppler; +cvar_t *s_backend;  static soundInterface_t si; @@ -371,6 +372,7 @@ void S_Init( void )  	s_volume = Cvar_Get( "s_volume", "0.8", CVAR_ARCHIVE );  	s_musicVolume = Cvar_Get( "s_musicvolume", "0.25", CVAR_ARCHIVE );  	s_doppler = Cvar_Get( "s_doppler", "1", CVAR_ARCHIVE ); +	s_backend = Cvar_Get( "s_backend", "", CVAR_ROM );  	cv = Cvar_Get( "s_initsound", "1", 0 );  	if( !cv->integer ) { @@ -389,10 +391,12 @@ void S_Init( void )  		if( cv->integer ) {  			//OpenAL  			started = S_AL_Init( &si ); +			Cvar_Set( "s_backend", "OpenAL" );  		}  		if( !started ) {  			started = S_Base_Init( &si ); +			Cvar_Set( "s_backend", "base" );  		}  		if( started ) { diff --git a/src/client/snd_mix.c b/src/client/snd_mix.c index 85b10cba..4d9e716a 100644 --- a/src/client/snd_mix.c +++ b/src/client/snd_mix.c @@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  */  // snd_mix.c -- portable code to mix sounds for snd_dma.c +#include "client.h"  #include "snd_local.h"  #if idppc_altivec && !defined(MACOS_X)  #include <altivec.h> @@ -138,6 +139,9 @@ void S_TransferStereo16 (unsigned long *pbuf, int endtime)  		snd_p += snd_linear_count;  		ls_paintedtime += (snd_linear_count>>1); + +		if( CL_VideoRecording( ) ) +			CL_WriteAVIAudioFrame( (byte *)snd_out, snd_linear_count << 1 );  	}  } diff --git a/src/qcommon/common.c b/src/qcommon/common.c index 231f4aa8..b0cee0d3 100644 --- a/src/qcommon/common.c +++ b/src/qcommon/common.c @@ -2714,316 +2714,6 @@ void Com_Shutdown (void) {  } -#if I_WANT_A_CUSTOM_MEMCPY && !defined(_WIN32) -void Com_Memcpy (void* dest, const void* src, const size_t count) -{ -	memcpy(dest, src, count); -} - -void Com_Memset (void* dest, const int val, const size_t count) -{ -	memset(dest, val, count); -} - -#elif I_WANT_A_CUSTOM_MEMCPY && defined(_WIN32) - -typedef enum -{ -	PRE_READ,									// prefetch assuming that buffer is used for reading only -	PRE_WRITE,									// prefetch assuming that buffer is used for writing only -	PRE_READ_WRITE								// prefetch assuming that buffer is used for both reading and writing -} e_prefetch; - -void Com_Prefetch (const void *s, const unsigned int bytes, e_prefetch type); - -#define EMMS_INSTRUCTION	__asm emms - -void _copyDWord (unsigned int* dest, const unsigned int constant, const unsigned int count) { -	__asm -	{ -			mov		edx,dest -			mov		eax,constant -			mov		ecx,count -			and		ecx,~7 -			jz		padding -			sub		ecx,8 -			jmp		loopu -			align	16 -loopu:		 -			test	[edx+ecx*4 + 28],ebx		// fetch next block destination to L1 cache -			mov		[edx+ecx*4 + 0],eax -			mov		[edx+ecx*4 + 4],eax -			mov		[edx+ecx*4 + 8],eax -			mov		[edx+ecx*4 + 12],eax -			mov		[edx+ecx*4 + 16],eax -			mov		[edx+ecx*4 + 20],eax -			mov		[edx+ecx*4 + 24],eax -			mov		[edx+ecx*4 + 28],eax -			sub		ecx,8 -			jge		loopu -padding:	mov		ecx,count -			mov		ebx,ecx -			and		ecx,7 -			jz		outta -			and		ebx,~7 -			lea		edx,[edx+ebx*4]				// advance dest pointer -			test	[edx+0],eax					// fetch destination to L1 cache -			cmp		ecx,4 -			jl		skip4 -			mov		[edx+0],eax -			mov		[edx+4],eax -			mov		[edx+8],eax -			mov		[edx+12],eax -			add		edx,16 -			sub		ecx,4 -skip4:		cmp		ecx,2 -			jl		skip2 -			mov		[edx+0],eax -			mov		[edx+4],eax -			add		edx,8 -			sub		ecx,2 -skip2:		cmp		ecx,1 -			jl		outta -			mov		[edx+0],eax -outta: -	} -} - -// optimized memory copy routine that handles all alignment -// cases and block sizes efficiently -void Com_Memcpy (void* dest, const void* src, const size_t count) { -	Com_Prefetch (src, count, PRE_READ); -	__asm -	{ -		push	edi -		push	esi -		mov		ecx,count -		cmp		ecx,0						// count = 0 check (just to be on the safe side) -		je		outta -		mov		edx,dest -		mov		ebx,src -		cmp		ecx,32						// padding only? -		jl		padding - -		mov		edi,ecx					 -		and		edi,~31					// edi = count&~31 -		sub		edi,32 - -		align 16 -loopMisAligned: -		mov		eax,[ebx + edi + 0 + 0*8] -		mov		esi,[ebx + edi + 4 + 0*8] -		mov		[edx+edi+0 + 0*8],eax -		mov		[edx+edi+4 + 0*8],esi -		mov		eax,[ebx + edi + 0 + 1*8] -		mov		esi,[ebx + edi + 4 + 1*8] -		mov		[edx+edi+0 + 1*8],eax -		mov		[edx+edi+4 + 1*8],esi -		mov		eax,[ebx + edi + 0 + 2*8] -		mov		esi,[ebx + edi + 4 + 2*8] -		mov		[edx+edi+0 + 2*8],eax -		mov		[edx+edi+4 + 2*8],esi -		mov		eax,[ebx + edi + 0 + 3*8] -		mov		esi,[ebx + edi + 4 + 3*8] -		mov		[edx+edi+0 + 3*8],eax -		mov		[edx+edi+4 + 3*8],esi -		sub		edi,32 -		jge		loopMisAligned -		 -		mov		edi,ecx -		and		edi,~31 -		add		ebx,edi					// increase src pointer -		add		edx,edi					// increase dst pointer -		and		ecx,31					// new count -		jz		outta					// if count = 0, get outta here - -padding: -		cmp		ecx,16 -		jl		skip16 -		mov		eax,dword ptr [ebx] -		mov		dword ptr [edx],eax -		mov		eax,dword ptr [ebx+4] -		mov		dword ptr [edx+4],eax -		mov		eax,dword ptr [ebx+8] -		mov		dword ptr [edx+8],eax -		mov		eax,dword ptr [ebx+12] -		mov		dword ptr [edx+12],eax -		sub		ecx,16 -		add		ebx,16 -		add		edx,16 -skip16: -		cmp		ecx,8 -		jl		skip8 -		mov		eax,dword ptr [ebx] -		mov		dword ptr [edx],eax -		mov		eax,dword ptr [ebx+4] -		sub		ecx,8 -		mov		dword ptr [edx+4],eax -		add		ebx,8 -		add		edx,8 -skip8: -		cmp		ecx,4 -		jl		skip4 -		mov		eax,dword ptr [ebx]	// here 4-7 bytes -		add		ebx,4 -		sub		ecx,4 -		mov		dword ptr [edx],eax -		add		edx,4 -skip4:							// 0-3 remaining bytes -		cmp		ecx,2 -		jl		skip2 -		mov		ax,word ptr [ebx]	// two bytes -		cmp		ecx,3				// less than 3? -		mov		word ptr [edx],ax -		jl		outta -		mov		al,byte ptr [ebx+2]	// last byte -		mov		byte ptr [edx+2],al -		jmp		outta -skip2: -		cmp		ecx,1 -		jl		outta -		mov		al,byte ptr [ebx] -		mov		byte ptr [edx],al -outta: -		pop		esi -		pop		edi -	} -} - -void Com_Memset (void* dest, const int val, const size_t count) -{ -	unsigned int fillval; - -	if (count < 8) -	{ -		__asm -		{ -			mov		edx,dest -			mov		eax, val -			mov		ah,al -			mov		ebx,eax -			and		ebx, 0xffff -			shl		eax,16 -			add		eax,ebx				// eax now contains pattern -			mov		ecx,count -			cmp		ecx,4 -			jl		skip4 -			mov		[edx],eax			// copy first dword -			add		edx,4 -			sub		ecx,4 -	skip4:	cmp		ecx,2 -			jl		skip2 -			mov		word ptr [edx],ax	// copy 2 bytes -			add		edx,2 -			sub		ecx,2 -	skip2:	cmp		ecx,0 -			je		skip1 -			mov		byte ptr [edx],al	// copy single byte -	skip1: -		} -		return; -	} - -	fillval = val; -	 -	fillval = fillval|(fillval<<8); -	fillval = fillval|(fillval<<16);		// fill dword with 8-bit pattern - -	_copyDWord ((unsigned int*)(dest),fillval, count/4); -	 -	__asm									// padding of 0-3 bytes -	{ -		mov		ecx,count -		mov		eax,ecx -		and		ecx,3 -		jz		skipA -		and		eax,~3 -		mov		ebx,dest -		add		ebx,eax -		mov		eax,fillval -		cmp		ecx,2 -		jl		skipB -		mov		word ptr [ebx],ax -		cmp		ecx,2 -		je		skipA					 -		mov		byte ptr [ebx+2],al		 -		jmp		skipA -skipB:		 -		cmp		ecx,0 -		je		skipA -		mov		byte ptr [ebx],al -skipA: -	} -} - -qboolean Com_Memcmp (const void *src0, const void *src1, const unsigned int count) -{ -	unsigned int i; -	// MMX version anyone? - -	if (count >= 16) -	{ -		unsigned int *dw = (unsigned int*)(src0); -		unsigned int *sw = (unsigned int*)(src1); - -		unsigned int nm2 = count/16; -		for (i = 0; i < nm2; i+=4) -		{ -			unsigned int tmp = (dw[i+0]-sw[i+0])|(dw[i+1]-sw[i+1])| -						  (dw[i+2]-sw[i+2])|(dw[i+3]-sw[i+3]); -			if (tmp) -				return qfalse; -		} -	} -	if (count & 15) -	{ -		byte *d = (byte*)src0; -		byte *s = (byte*)src1; -		for (i = count & 0xfffffff0; i < count; i++) -		if (d[i]!=s[i]) -			return qfalse; -	} - -	return qtrue; -} - -void Com_Prefetch (const void *s, const unsigned int bytes, e_prefetch type) -{ -	// write buffer prefetching is performed only if -	// the processor benefits from it. Read and read/write -	// prefetching is always performed. - -	switch (type) -	{ -		case PRE_WRITE : break; -		case PRE_READ: -		case PRE_READ_WRITE: - -		__asm -		{ -			mov		ebx,s -			mov		ecx,bytes -			cmp		ecx,4096				// clamp to 4kB -			jle		skipClamp -			mov		ecx,4096 -skipClamp: -			add		ecx,0x1f -			shr		ecx,5					// number of cache lines -			jz		skip -			jmp		loopie - -			align 16 -	loopie:	test	byte ptr [ebx],al -			add		ebx,32 -			dec		ecx -			jnz		loopie -	skip: -		} - -		break; -	} -} -#endif  //------------------------------------------------------------------------ diff --git a/src/qcommon/files.c b/src/qcommon/files.c index 1ea34cc6..4ebca39a 100644 --- a/src/qcommon/files.c +++ b/src/qcommon/files.c @@ -56,7 +56,7 @@ The "cd path" is the path to an alternate hierarchy that will be searched if a f  is not located in the base path.  A user can do a partial install that copies some  data to a base path created on their hard drive and leave the rest on the cd.  Files  are never writen to the cd path.  It defaults to a value set by the installer, like -"e:\quake3", but it can be overridden with "+set ds_cdpath g:\quake3". +"e:\quake3", but it can be overridden with "+set fs_cdpath g:\quake3".  If a user runs the game directly from a CD, the base path would be on the CD.  This  should still function correctly, but all file writes will fail (harmlessly). @@ -201,7 +201,8 @@ or configs will never get loaded from disk!  // every time a new demo pk3 file is built, this checksum must be updated.  // the easiest way to get it is to just run the game and see what it spits out -#define	DEMO_PAK_CHECKSUM	437558517u +#define	DEMO_PAK0_CHECKSUM	2985612116u +#define	PAK0_CHECKSUM				1566731103u  // if this is defined, the executable positively won't work with any paks other  // than the demo pak, even if productid is present.  This is only used for our @@ -307,11 +308,6 @@ static char		*fs_serverReferencedPakNames[MAX_SEARCH_PATHS];		// pk3 names  char lastValidBase[MAX_OSPATH];  char lastValidGame[MAX_OSPATH]; -// productId: This file is copyright 1999 Id Software, and may not be duplicated except during a licensed installation of the full commercial version of Quake 3:Arena -static byte fs_scrambledProductId[152] = { -220, 129, 255, 108, 244, 163, 171, 55, 133, 65, 199, 36, 140, 222, 53, 99, 65, 171, 175, 232, 236, 193, 210, 250, 169, 104, 231, 231, 21, 201, 170, 208, 135, 175, 130, 136, 85, 215, 71, 23, 96, 32, 96, 83, 44, 240, 219, 138, 184, 215, 73, 27, 196, 247, 55, 139, 148, 68, 78, 203, 213, 238, 139, 23, 45, 205, 118, 186, 236, 230, 231, 107, 212, 1, 10, 98, 30, 20, 116, 180, 216, 248, 166, 35, 45, 22, 215, 229, 35, 116, 250, 167, 117, 3, 57, 55, 201, 229, 218, 222, 128, 12, 141, 149, 32, 110, 168, 215, 184, 53, 31, 147, 62, 12, 138, 67, 132, 54, 125, 6, 221, 148, 140, 4, 21, 44, 198, 3, 126, 12, 100, 236, 61, 42, 44, 251, 15, 135, 14, 134, 89, 92, 177, 246, 152, 106, 124, 78, 118, 80, 28, 42 -}; -  #ifdef FS_MISSING  FILE*		missingFiles = NULL;  #endif @@ -566,11 +562,22 @@ FS_Remove  ===========  */ -static void FS_Remove( const char *osPath ) { +void FS_Remove( const char *osPath ) {  	remove( osPath );  }  /* +=========== +FS_HomeRemove + +=========== +*/ +void FS_HomeRemove( const char *homePath ) { +	remove( FS_BuildOSPath( fs_homepath->string, +			fs_gamedir, homePath ) ); +} + +/*  ================  FS_FileExists @@ -2829,69 +2836,6 @@ static void FS_Startup( const char *gameName ) {  	Com_Printf( "%d files in pk3 files\n", fs_packFiles );  } - -/* -=================== -FS_SetRestrictions - -Looks for product keys and restricts media add on ability -if the full version is not found -=================== -*/ -static void FS_SetRestrictions( void ) { -	searchpath_t	*path; -	char			*productId; - -	return; - -#ifndef PRE_RELEASE_DEMO - -	// if fs_restrict is set, don't even look for the id file, -	// which allows the demo release to be tested even if -	// the full game is present -	if ( !fs_restrict->integer ) { -		// look for the full game id -		FS_ReadFile( "productid.txt", (void **)&productId ); -		if ( productId ) { -			// check against the hardcoded string -			int		seed, i; - -			seed = 5000; -			for ( i = 0 ; i < sizeof( fs_scrambledProductId ) ; i++ ) { -				if ( ( fs_scrambledProductId[i] ^ (seed&255) ) != productId[i] ) { -					break; -				} -				seed = (69069 * seed + 1); -			} - -			FS_FreeFile( productId ); - -			if ( i == sizeof( fs_scrambledProductId ) ) { -				return;	// no restrictions -			} -			Com_Error( ERR_FATAL, "Invalid product identification" ); -		} -	} -#endif -	Cvar_Set( "fs_restrict", "1" ); - -	Com_Printf( "\nRunning in restricted demo mode.\n\n" ); - -	// restart the filesystem with just the demo directory -	FS_Shutdown(qfalse); -	FS_Startup( DEMOGAME ); - -	// make sure that the pak file has the header checksum we expect -	for ( path = fs_searchpaths ; path ; path = path->next ) { -		if ( path->pack ) { -			// a tiny attempt to keep the checksum from being scannable from the exe -			if ( (path->pack->checksum ^ 0x02261994u) != (DEMO_PAK_CHECKSUM ^ 0x02261994u) ) { -				Com_Error( ERR_FATAL, "Corrupted pak0.pk3: %u", path->pack->checksum ); -			} -		} -	} -} -  /*  =====================  FS_GamePureChecksum @@ -3259,9 +3203,6 @@ void FS_InitFilesystem( void ) {  	// try to start up normally  	FS_Startup( BASEGAME ); -	// see if we are going to allow add-ons -	FS_SetRestrictions(); -  	// if we can't find default.cfg, assume that the paths are  	// busted and error out now, rather than getting an unreadable  	// graphics screen when the font fails to load @@ -3296,9 +3237,6 @@ void FS_Restart( int checksumFeed ) {  	// try to start up normally  	FS_Startup( BASEGAME ); -	// see if we are going to allow add-ons -	FS_SetRestrictions(); -  	// if we can't find default.cfg, assume that the paths are  	// busted and error out now, rather than getting an unreadable  	// graphics screen when the font fails to load diff --git a/src/qcommon/md4.c b/src/qcommon/md4.c index 24b79610..82c4b0d8 100644 --- a/src/qcommon/md4.c +++ b/src/qcommon/md4.c @@ -38,13 +38,8 @@ void MD4Init (MD4_CTX *);  void MD4Update (MD4_CTX *, const unsigned char *, unsigned int);  void MD4Final (unsigned char [16], MD4_CTX *); -#if I_WANT_A_CUSTOM_MEMCPY -void Com_Memset (void* dest, const int val, const size_t count); -void Com_Memcpy (void* dest, const void* src, const size_t count); -#else  #define Com_Memset memset  #define Com_Memcpy memcpy -#endif  /* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm */  /* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h index 53848aa4..537dee36 100644 --- a/src/qcommon/q_shared.h +++ b/src/qcommon/q_shared.h @@ -243,13 +243,8 @@ void Snd_Memset (void* dest, const int val, const size_t count);  #define Snd_Memset Com_Memset  #endif -#if I_WANT_A_CUSTOM_MEMCPY -void Com_Memset (void* dest, const int val, const size_t count); -void Com_Memcpy (void* dest, const void* src, const size_t count); -#else  #define Com_Memset memset  #define Com_Memcpy memcpy -#endif  #define CIN_system	1  #define CIN_loop	2 diff --git a/src/qcommon/qcommon.h b/src/qcommon/qcommon.h index 843f04ef..9e9ca513 100644 --- a/src/qcommon/qcommon.h +++ b/src/qcommon/qcommon.h @@ -651,6 +651,9 @@ qboolean FS_ComparePaks( char *neededpaks, int len, qboolean dlstring );  void FS_Rename( const char *from, const char *to ); +void FS_Remove( const char *osPath ); +void FS_HomeRemove( const char *homePath ); +  /*  ============================================================== @@ -892,7 +895,6 @@ void S_ClearSoundBuffer( void );  void SCR_DebugGraph (float value, int color);	// FIXME: move logging to common? -  //  // server interface  // diff --git a/src/renderer/tr_backend.c b/src/renderer/tr_backend.c index 73449586..9c9b841a 100644 --- a/src/renderer/tr_backend.c +++ b/src/renderer/tr_backend.c @@ -1082,6 +1082,9 @@ void RB_ExecuteRenderCommands( const void *data ) {  		case RC_SCREENSHOT:  			data = RB_TakeScreenshotCmd( data );  			break; +		case RC_VIDEOFRAME: +			data = RB_TakeVideoFrameCmd( data ); +			break;  		case RC_END_OF_LIST:  		default: diff --git a/src/renderer/tr_cmds.c b/src/renderer/tr_cmds.c index bbcf6385..d637aec0 100644 --- a/src/renderer/tr_cmds.c +++ b/src/renderer/tr_cmds.c @@ -446,3 +446,30 @@ void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {  	backEnd.pc.msec = 0;  } +/* +============= +RE_TakeVideoFrame +============= +*/ +void RE_TakeVideoFrame( int width, int height, +		byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg ) +{ +	videoFrameCommand_t	*cmd; + +	if( !tr.registered ) { +		return; +	} + +	cmd = R_GetCommandBuffer( sizeof( *cmd ) ); +	if( !cmd ) { +		return; +	} + +	cmd->commandId = RC_VIDEOFRAME; + +	cmd->width = width; +	cmd->height = height; +	cmd->captureBuffer = captureBuffer; +	cmd->encodeBuffer = encodeBuffer; +	cmd->motionJpeg = motionJpeg; +} diff --git a/src/renderer/tr_image.c b/src/renderer/tr_image.c index a3efa2f1..692f00c6 100644 --- a/src/renderer/tr_image.c +++ b/src/renderer/tr_image.c @@ -1853,6 +1853,64 @@ void SaveJPG(char * filename, int quality, int image_width, int image_height, un    /* And we're done! */  } +/* +================= +SaveJPGToBuffer +================= +*/ +int SaveJPGToBuffer( byte *buffer, int quality, +    int image_width, int image_height, +    byte *image_buffer ) +{ +  struct jpeg_compress_struct cinfo; +  struct jpeg_error_mgr jerr; +  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */ +  int row_stride;		/* physical row width in image buffer */ + +  /* Step 1: allocate and initialize JPEG compression object */ +  cinfo.err = jpeg_std_error(&jerr); +  /* Now we can initialize the JPEG compression object. */ +  jpeg_create_compress(&cinfo); + +  /* Step 2: specify data destination (eg, a file) */ +  /* Note: steps 2 and 3 can be done in either order. */ +  jpegDest(&cinfo, buffer, image_width*image_height*4); + +  /* Step 3: set parameters for compression */ +  cinfo.image_width = image_width; 	/* image width and height, in pixels */ +  cinfo.image_height = image_height; +  cinfo.input_components = 4;		/* # of color components per pixel */ +  cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */ + +  jpeg_set_defaults(&cinfo); +  jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); + +  /* Step 4: Start compressor */ +  jpeg_start_compress(&cinfo, TRUE); + +  /* Step 5: while (scan lines remain to be written) */ +  /*           jpeg_write_scanlines(...); */ +  row_stride = image_width * 4;	/* JSAMPLEs per row in image_buffer */ + +  while (cinfo.next_scanline < cinfo.image_height) { +    /* jpeg_write_scanlines expects an array of pointers to scanlines. +     * Here the array is only one element long, but you could pass +     * more than one scanline at a time if that's more convenient. +     */ +    row_pointer[0] = & image_buffer[((cinfo.image_height-1)*row_stride)-cinfo.next_scanline * row_stride]; +    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); +  } + +  /* Step 6: Finish compression */ +  jpeg_finish_compress(&cinfo); + +  /* Step 7: release JPEG compression object */ +  jpeg_destroy_compress(&cinfo); + +  /* And we're done! */ +  return hackSize; +} +  //===================================================================  /* diff --git a/src/renderer/tr_init.c b/src/renderer/tr_init.c index a3fd2ca6..79c910d1 100644 --- a/src/renderer/tr_init.c +++ b/src/renderer/tr_init.c @@ -701,6 +701,51 @@ void R_ScreenShotJPEG_f (void) {  //============================================================================  /* +================== +RB_TakeVideoFrameCmd +================== +*/ +const void *RB_TakeVideoFrameCmd( const void *data ) +{ +	const videoFrameCommand_t	*cmd; +	int												frameSize; +	int												i; +	 +	cmd = (const videoFrameCommand_t *)data; +	 +	qglReadPixels( 0, 0, cmd->width, cmd->height, GL_RGBA, +			GL_UNSIGNED_BYTE, cmd->captureBuffer ); + +	// gamma correct +	if( ( tr.overbrightBits > 0 ) && glConfig.deviceSupportsGamma ) +		R_GammaCorrect( cmd->captureBuffer, cmd->width * cmd->height * 4 ); + +	if( cmd->motionJpeg ) +	{ +		frameSize = SaveJPGToBuffer( cmd->encodeBuffer, 95, +				cmd->width, cmd->height, cmd->captureBuffer ); +	} +	else +	{ +		frameSize = cmd->width * cmd->height * 4; + +		// Vertically flip the image +		for( i = 0; i < cmd->height; i++ ) +		{ +			Com_Memcpy( &cmd->encodeBuffer[ i * ( cmd->width * 4 ) ], +					&cmd->captureBuffer[ ( cmd->height - i - 1 ) * ( cmd->width * 4 ) ], +					cmd->width * 4 ); +		} +	} + +	ri.CL_WriteAVIVideoFrame( cmd->encodeBuffer, frameSize ); + +	return (const void *)(cmd + 1);	 +} + +//============================================================================ + +/*  ** GL_SetDefaultState  */  void GL_SetDefaultState( void ) @@ -1202,5 +1247,7 @@ refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) {  	re.GetEntityToken = R_GetEntityToken;  	re.inPVS = R_inPVS; +	re.TakeVideoFrame = RE_TakeVideoFrame; +  	return &re;  } diff --git a/src/renderer/tr_local.h b/src/renderer/tr_local.h index 4119efac..7efed35d 100644 --- a/src/renderer/tr_local.h +++ b/src/renderer/tr_local.h @@ -1216,6 +1216,7 @@ skin_t	*R_GetSkinByHandle( qhandle_t hSkin );  int R_ComputeLOD( trRefEntity_t *ent ); +const void *RB_TakeVideoFrameCmd( const void *data );  //  // tr_shader.c @@ -1580,6 +1581,15 @@ typedef struct {  	qboolean jpeg;  } screenshotCommand_t; +typedef struct { +	int						commandId; +	int						width; +	int						height; +	byte					*captureBuffer; +	byte					*encodeBuffer; +	qboolean			motionJpeg; +} videoFrameCommand_t; +  typedef enum {  	RC_END_OF_LIST,  	RC_SET_COLOR, @@ -1587,7 +1597,8 @@ typedef enum {  	RC_DRAW_SURFS,  	RC_DRAW_BUFFER,  	RC_SWAP_BUFFERS, -	RC_SCREENSHOT +	RC_SCREENSHOT, +	RC_VIDEOFRAME  } renderCommand_t; @@ -1636,6 +1647,11 @@ void RE_StretchPic ( float x, float y, float w, float h,  void RE_BeginFrame( stereoFrame_t stereoFrame );  void RE_EndFrame( int *frontEndMsec, int *backEndMsec );  void SaveJPG(char * filename, int quality, int image_width, int image_height, unsigned char *image_buffer); +int SaveJPGToBuffer( byte *buffer, int quality, +		int image_width, int image_height, +		byte *image_buffer ); +void RE_TakeVideoFrame( int width, int height, +		byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg );  // font stuff  void R_InitFreeType( void ); diff --git a/src/renderer/tr_public.h b/src/renderer/tr_public.h index 92801ac4..e4e4d047 100644 --- a/src/renderer/tr_public.h +++ b/src/renderer/tr_public.h @@ -98,6 +98,8 @@ typedef struct {  	void	(*RemapShader)(const char *oldShader, const char *newShader, const char *offsetTime);  	qboolean (*GetEntityToken)( char *buffer, int size );  	qboolean (*inPVS)( const vec3_t p1, const vec3_t p2 ); + +	void (*TakeVideoFrame)( int h, int w, byte* captureBuffer, byte *encodeBuffer, qboolean motionJpeg );  } refexport_t;  // @@ -157,6 +159,7 @@ typedef struct {  	int		(*CIN_PlayCinematic)( const char *arg0, int xpos, int ypos, int width, int height, int bits);  	e_status (*CIN_RunCinematic) (int handle); +	void	(*CL_WriteAVIVideoFrame)( const byte *buffer, int size );  } refimport_t; diff --git a/src/unix/Makefile b/src/unix/Makefile index 793f3c7e..db7802dd 100644 --- a/src/unix/Makefile +++ b/src/unix/Makefile @@ -21,6 +21,12 @@ else    COMPILE_ARCH=$(shell uname -m | sed -e s/i.86/i386/)  endif +BUILD_CLIENT     = +BUILD_CLIENT_SMP = +BUILD_SERVER     = +BUILD_GAME_SO    = +BUILD_GAME_QVM   = +  #############################################################################  #  # If you require a different configuration from the defaults below, create a @@ -90,14 +96,6 @@ ifndef USE_LOCAL_HEADERS  USE_LOCAL_HEADERS=1  endif -ifndef BUILD_CLIENT -BUILD_CLIENT=1 -endif - -ifndef BUILD_SERVER -BUILD_SERVER=1 -endif -  #############################################################################  BD=debug-$(PLATFORM)-$(ARCH) @@ -135,7 +133,6 @@ MKDIR=mkdir  ifeq ($(PLATFORM),linux) -  GLIBC=-glibc    CC=gcc    ifeq ($(ARCH),alpha) @@ -227,23 +224,6 @@ ifeq ($(PLATFORM),linux)      LDFLAGS+=-m32    endif -  ifeq ($(ARCH),axp) -    TARGETS=\ -      $(B)/$(PLATFORM)tremded -  else -    TARGETS=\ -      $(B)/$(PLATFORM)tremulous \ -      $(B)/$(PLATFORM)tremded \ -      $(B)/base/cgame$(ARCH).$(SHLIBEXT) \ -      $(B)/base/qagame$(ARCH).$(SHLIBEXT) \ -      $(B)/base/ui$(ARCH).$(SHLIBEXT)     \ -      $(B)/base/vm/cgame.qvm \ -      $(B)/base/vm/qagame.qvm \ -      $(B)/base/vm/ui.qvm -#      $(B)/$(PLATFORM)tremulous-smp \ - -  endif -  else # ifeq Linux  ############################################################################# @@ -251,7 +231,6 @@ else # ifeq Linux  #############################################################################  ifeq ($(PLATFORM),darwin) -  GLIBC=    CC=gcc    # !!! FIXME: calling conventions are still broken! See Bugzilla #2519 @@ -326,17 +305,6 @@ ifeq ($(PLATFORM),darwin)      endif    endif -  TARGETS=\ -      $(B)/$(PLATFORM)tremulous \ -      $(B)/$(PLATFORM)tremded \ -      $(B)/base/cgame$(ARCH).$(SHLIBEXT) \ -      $(B)/base/qagame$(ARCH).$(SHLIBEXT) \ -      $(B)/base/ui$(ARCH).$(SHLIBEXT)     \ -      $(B)/base/vm/cgame.qvm \ -      $(B)/base/vm/qagame.qvm \ -      $(B)/base/vm/ui.qvm -      $(B)/$(PLATFORM)tremulous-smp \ -  else # ifeq darwin @@ -382,14 +350,8 @@ ifeq ($(PLATFORM),mingw32)      LDFLAGS+=-m32    endif -  TARGETS=\ -    $(B)/$(PLATFORM)tremulous$(BINEXT) \ -    $(B)/base/cgame$(ARCH).$(SHLIBEXT) \ -    $(B)/base/qagame$(ARCH).$(SHLIBEXT) \ -    $(B)/base/ui$(ARCH).$(SHLIBEXT)     \ -    $(B)/base/vm/cgame.qvm \ -    $(B)/base/vm/qagame.qvm \ -    $(B)/base/vm/ui.qvm +  BUILD_SERVER = 0 +  BUILD_CLIENT_SMP = 0  else # ifeq mingw32 @@ -399,8 +361,6 @@ else # ifeq mingw32  ifeq ($(PLATFORM),freebsd) -  GLIBC= #libc is irrelevant -    ifneq (,$(findstring alpha,$(shell uname -m)))      ARCH=axp    else #default to i386 @@ -441,21 +401,6 @@ ifeq ($(PLATFORM),freebsd)    CLIENT_LDFLAGS=-L/usr/X11R6/$(LIB) -lGL -lX11 -lXext -lXxf86dga -lXxf86vm -  ifeq ($(ARCH),axp) -    TARGETS=\ -      $(B)/$(PLATFORM)tremded -  else -    TARGETS=\ -      $(B)/$(PLATFORM)tremulous \ -      $(B)/$(PLATFORM)tremded \ -      $(B)/base/cgame$(ARCH).$(SHLIBEXT) \ -      $(B)/base/qagame$(ARCH).$(SHLIBEXT) \ -      $(B)/base/ui$(ARCH).$(SHLIBEXT)     \ -      $(B)/base/vm/cgame.qvm \ -      $(B)/base/vm/qagame.qvm \ -      $(B)/base/vm/ui.qvm -  endif -  else # ifeq freebsd  ############################################################################# @@ -482,17 +427,8 @@ ifeq ($(PLATFORM),netbsd)      BASE_CFLAGS += -DNO_VM_COMPILED    endif -  ifeq ($(ARCH),i386) -    TARGETS=\ -      $(B)/base/cgame$(ARCH).$(SHLIBEXT) \ -      $(B)/base/qagame$(ARCH).$(SHLIBEXT) \ -      $(B)/base/ui$(ARCH).$(SHLIBEXT)     \ -      $(B)/$(PLATFORM)tremded -  else -    TARGETS=\ -      $(B)/$(PLATFORM)tremded - -  endif +  BUILD_CLIENT = 0 +  BUILD_GAME_QVM = 0  else # ifeq netbsd @@ -503,7 +439,6 @@ else # ifeq netbsd  ifeq ($(PLATFORM),irix)    ARCH=mips  #default to MIPS -  GLIBC=  #libc is irrelevant    CC=cc    BASE_CFLAGS=-Dstricmp=strcasecmp -Xcpluscomm -woff 1185 -mips3 \ @@ -518,9 +453,6 @@ ifeq ($(PLATFORM),irix)    LDFLAGS=-ldl -lm    CLIENT_LDFLAGS=-L/usr/X11/$(LIB) -lGL -lX11 -lXext -lm -  TARGETS=$(B)/$(PLATFORM)tremulous \ -    $(B)/$(PLATFORM)tremded -  else # ifeq IRIX  ############################################################################# @@ -529,7 +461,6 @@ else # ifeq IRIX  ifeq ($(PLATFORM),SunOS) -  GLIBC= #libc is irrelevant    CC=gcc    INSTALL=ginstall    MKDIR=gmkdir @@ -560,9 +491,9 @@ ifeq ($(PLATFORM),SunOS)    OPTIMIZE = -O3 -ffast-math -funroll-loops    ifeq ($(ARCH),sparc) -    OPTIMIZE = -O0 -ffast-math -falign-loops=2 \ +    OPTIMIZE = -O3 -ffast-math -falign-loops=2 \        -falign-jumps=2 -falign-functions=2 -fstrength-reduce \ -      -mtune=ultrasparc -mv8plus -munaligned-doubles \ +      -mtune=ultrasparc -mv8plus -mno-faster-structs \        -funroll-loops      BASE_CFLAGS += -DNO_VM_COMPILED    else @@ -584,6 +515,8 @@ ifeq ($(PLATFORM),SunOS)    THREAD_LDFLAGS=-lpthread    LDFLAGS=-lsocket -lnsl -ldl -lm +  BOTCFLAGS=-O0 +    ifeq ($(USE_SDL),1)      CLIENT_LDFLAGS=$(shell sdl-config --libs) -L/usr/X11/lib -lGLU -lX11 -lXext    else @@ -596,31 +529,6 @@ ifeq ($(PLATFORM),SunOS)      LDFLAGS+=-m32    endif -  ifeq ($(ARCH),sparc) -    TARGETS=\ -      $(B)/$(PLATFORM)tremulous \ -      $(B)/$(PLATFORM)tremded \ -      $(B)/base/cgame$(ARCH).$(SHLIBEXT) \ -      $(B)/base/qagame$(ARCH).$(SHLIBEXT) \ -      $(B)/base/ui$(ARCH).$(SHLIBEXT)     \ -      $(B)/base/vm/cgame.qvm \ -      $(B)/base/vm/qagame.qvm \ -      $(B)/base/vm/ui.qvm \ -      $(B)/$(PLATFORM)tremulous-smp -  else -    TARGETS=\ -      $(B)/$(PLATFORM)tremulous \ -      $(B)/$(PLATFORM)tremded \ -      $(B)/base/cgame$(ARCH).$(SHLIBEXT) \ -      $(B)/base/qagame$(ARCH).$(SHLIBEXT) \ -      $(B)/base/ui$(ARCH).$(SHLIBEXT)     \ -      $(B)/base/vm/cgame.qvm \ -      $(B)/base/vm/qagame.qvm \ -      $(B)/base/vm/ui.qvm \ -      $(B)/$(PLATFORM)tremulous-smp - -  endif -  else # ifeq SunOS  ############################################################################# @@ -635,12 +543,6 @@ else # ifeq SunOS    SHLIBCFLAGS=-fPIC    SHLIBLDFLAGS=-shared -  TARGETS=\ -    $(B)/base/cgame$(ARCH).$(SHLIBEXT) \ -    $(B)/base/qagame$(ARCH).$(SHLIBEXT) \ -    $(B)/base/ui$(ARCH).$(SHLIBEXT) \ -    $(B)/$(PLATFORM)tremded -  endif #Linux  endif #darwin  endif #mingw32 @@ -649,30 +551,38 @@ endif #NetBSD  endif #IRIX  endif #SunOS -ifeq ($(USE_CCACHE),1) -  CC := ccache $(CC) +TARGETS = + +ifneq ($(BUILD_SERVER),0) +  TARGETS += $(B)/tremded.$(ARCH)$(BINEXT)  endif -ifneq ($(BUILD_SERVER),1) -  TARGETS := $(subst $(B)/$(PLATFORM)tremded,,$(TARGETS)) +ifneq ($(BUILD_CLIENT),0) +  TARGETS += $(B)/tremulous.$(ARCH)$(BINEXT) +  ifneq ($(BUILD_CLIENT_SMP),0) +    TARGETS += $(B)/tremulous.$(ARCH)$(BINEXT) +  endif  endif -ifneq ($(BUILD_CLIENT),1) -  TARGETS := \ -  $(subst $(B)/base/cgame$(ARCH).$(SHLIBEXT),,\ -  $(subst $(B)/base/ui$(ARCH).$(SHLIBEXT),,\ -  $(subst $(B)/base/vm/cgame.qvm,,\ -  $(subst $(B)/base/vm/ui.qvm,,\ -  $(subst $(B)/$(PLATFORM)tremulous-smp$(BINEXT),,\ -  $(subst $(B)/$(PLATFORM)tremulous$(BINEXT),,$(TARGETS) )))))) +ifneq ($(BUILD_GAME_SO),0) +  TARGETS += \ +    $(B)/base/cgame$(ARCH).$(SHLIBEXT) \ +    $(B)/base/qagame$(ARCH).$(SHLIBEXT) \ +    $(B)/base/ui$(ARCH).$(SHLIBEXT)  endif -# Never build qvms when cross-compiling -ifeq ($(CROSS_COMPILING),1) -  TARGETS := \ -  $(subst $(B)/base/vm/qagame.qvm,,\ -  $(subst $(B)/base/vm/cgame.qvm,,\ -  $(subst $(B)/base/vm/ui.qvm,,$(TARGETS) ))) +ifneq ($(BUILD_GAME_QVM),0) +  ifneq ($(CROSS_COMPILING),1) +    TARGETS += \ +      $(B)/base/vm/cgame.qvm \ +      $(B)/base/vm/qagame.qvm \ +      $(B)/base/vm/ui.qvm \ +      qvmdeps +  endif +endif + +ifeq ($(USE_CCACHE),1) +  CC := ccache $(CC)  endif  ifdef DEFAULT_BASEDIR @@ -691,7 +601,7 @@ endif  DO_CC=$(CC) $(NOTSHLIBCFLAGS) $(CFLAGS) -o $@ -c $<  DO_SMP_CC=$(CC) $(NOTSHLIBCFLAGS) $(CFLAGS) -DSMP -o $@ -c $< -DO_BOT_CC=$(CC) $(NOTSHLIBCFLAGS) $(CFLAGS) -DBOTLIB -o $@ -c $<   # $(SHLIBCFLAGS) # bk001212 +DO_BOT_CC=$(CC) $(NOTSHLIBCFLAGS) $(CFLAGS) $(BOTCFLAGS) -DBOTLIB -o $@ -c $<   # $(SHLIBCFLAGS) # bk001212  DO_DEBUG_CC=$(CC) $(NOTSHLIBCFLAGS) $(DEBUG_CFLAGS) -o $@ -c $<  DO_SHLIB_CC=$(CC) $(CFLAGS) $(SHLIBCFLAGS) -o $@ -c $<  DO_SHLIB_DEBUG_CC=$(CC) $(DEBUG_CFLAGS) $(SHLIBCFLAGS) -o $@ -c $< @@ -767,6 +677,7 @@ Q3OBJ = \    $(B)/client/cl_parse.o \    $(B)/client/cl_scrn.o \    $(B)/client/cl_ui.o \ +  $(B)/client/cl_avi.o \    \    $(B)/client/cm_load.o \    $(B)/client/cm_patch.o \ @@ -901,12 +812,21 @@ Q3OBJ = \    $(B)/client/tr_surface.o \    $(B)/client/tr_world.o \ -  ifeq ($(ARCH),i386)    Q3OBJ += $(B)/client/vm_x86.o +  Q3OBJ += \ +    $(B)/client/snd_mixa.o \ +    $(B)/client/matha.o \ +    $(B)/client/ftola.o \ +    $(B)/client/snapvectora.o  endif  ifeq ($(ARCH),x86)    Q3OBJ += $(B)/client/vm_x86.o +  Q3OBJ += \ +    $(B)/client/snd_mixa.o \ +    $(B)/client/matha.o \ +    $(B)/client/ftola.o \ +    $(B)/client/snapvectora.o  endif  ifeq ($(ARCH),x86_64)    Q3OBJ += $(B)/client/vm_x86_64.o @@ -918,48 +838,9 @@ ifeq ($(ARCH),ppc)    endif  endif -#platform specific objects -ifeq ($(PLATFORM),freebsd) -ifeq ($(ARCH),axp) -  Q3POBJ= -else -  Q3POBJ=\ -    $(B)/client/unix_main.o \ -    $(B)/client/unix_net.o \ -    $(B)/client/unix_shared.o \ -    $(B)/client/linux_signals.o \ -    $(B)/client/linux_common.o \ -    $(B)/client/linux_qgl.o \ -    $(B)/client/sdl_glimp.o \ -    $(B)/client/linux_glimp.o \ -    $(B)/client/linux_snd.o \ -    $(B)/client/sdl_snd.o \ -    $(B)/client/snd_mixa.o \ -    $(B)/client/matha.o -  ifeq ($(ARCH),i386) -    Q3POBJ += $(B)/client/ftola.o $(B)/client/snapvectora.o -    Q3POBJ_SMP += $(B)/client/ftola.o $(B)/client/snapvectora.o -  endif - -endif # FreeBSD-axp -else -ifeq ($(PLATFORM),irix) -  Q3POBJ=\ -    $(B)/client/unix_main.o \ -    $(B)/client/unix_net.o \ -    $(B)/client/unix_shared.o \ -    $(B)/client/irix_qgl.o \ -    $(B)/client/irix_glimp.o \ -    $(B)/client/irix_snd.o -else  ifeq ($(PLATFORM),mingw32) -  Q3POBJ=\ -    $(B)/client/linux_common.o \ -    $(B)/client/snd_mixa.o \ -    $(B)/client/matha.o \ -    $(B)/client/ftola.o \ -    $(B)/client/snapvectora.o \ +  Q3OBJ += \      $(B)/client/win_gamma.o \      $(B)/client/win_glimp.o \      $(B)/client/win_input.o \ @@ -972,123 +853,38 @@ ifeq ($(PLATFORM),mingw32)      $(B)/client/win_wndproc.o \      $(B)/client/win_resource.o  else -ifeq ($(PLATFORM),linux) -ifeq ($(ARCH),axp) -  Q3POBJ= -else -  Q3POBJ=\ -    $(B)/client/unix_main.o \ -    $(B)/client/unix_net.o \ -    $(B)/client/unix_shared.o \ -    $(B)/client/linux_signals.o \ -    $(B)/client/linux_common.o \ -    $(B)/client/linux_qgl.o \ -    $(B)/client/linux_glimp.o \ -    $(B)/client/sdl_glimp.o \ -    $(B)/client/linux_joystick.o \ -    $(B)/client/linux_snd.o \ -    $(B)/client/sdl_snd.o \ -    $(B)/client/snd_mixa.o \ -    $(B)/client/matha.o \ - -  Q3POBJ_SMP=\ +  Q3OBJ += \      $(B)/client/unix_main.o \      $(B)/client/unix_net.o \      $(B)/client/unix_shared.o \      $(B)/client/linux_signals.o \ -    $(B)/client/linux_common.o \      $(B)/client/linux_qgl.o \ -    $(B)/client/linux_glimp_smp.o \ -    $(B)/client/linux_joystick.o \      $(B)/client/linux_snd.o \ -    $(B)/client/sdl_snd.o \ -    $(B)/client/snd_mixa.o \ -    $(B)/client/matha.o +    $(B)/client/sdl_snd.o -  ifeq ($(ARCH),i386) -    Q3POBJ += $(B)/client/ftola.o $(B)/client/snapvectora.o -    Q3POBJ_SMP += $(B)/client/ftola.o $(B)/client/snapvectora.o +  ifeq ($(PLATFORM),linux) +    Q3OBJ += $(B)/client/linux_joystick.o    endif -endif #Linux-axp - -else -ifeq ($(PLATFORM),darwin) -  Q3POBJ=\ -    $(B)/client/unix_main.o \ -    $(B)/client/unix_net.o \ -    $(B)/client/unix_shared.o \ -    $(B)/client/linux_signals.o \ -    $(B)/client/linux_common.o \ -    $(B)/client/linux_qgl.o \ -    $(B)/client/linux_glimp.o \ -    $(B)/client/sdl_glimp.o \ -    $(B)/client/linux_joystick.o \ -    $(B)/client/linux_snd.o \ -    $(B)/client/sdl_snd.o \ - -  Q3POBJ_SMP=\ -    $(B)/client/unix_main.o \ -    $(B)/client/unix_net.o \ -    $(B)/client/unix_shared.o \ -    $(B)/client/linux_signals.o \ -    $(B)/client/linux_common.o \ -    $(B)/client/linux_qgl.o \ -    $(B)/client/sdl_glimp_smp.o \ -    $(B)/client/linux_joystick.o \ -    $(B)/client/linux_snd.o \ -    $(B)/client/sdl_snd.o \ -  ifeq ($(ARCH),i386) -    I386OBJS := \ -      $(B)/client/ftola.o \ -      $(B)/client/snapvectora.o \ -      $(B)/client/snd_mixa.o \ -      $(B)/client/matha.o \ - -    Q3POBJ += $(I386OBJS) -    Q3POBJ_SMP += $(I386OBJS) +  ifeq ($(USE_SDL),1) +    ifneq ($(PLATFORM),darwin) +      BUILD_CLIENT_SMP = 0 +    endif    endif -else -ifeq ($(PLATFORM),SunOS) -  Q3POBJ=\ -    $(B)/client/unix_main.o \ -    $(B)/client/unix_net.o \ -    $(B)/client/unix_shared.o \ -    $(B)/client/linux_signals.o \ -    $(B)/client/linux_common.o \ -    $(B)/client/linux_qgl.o \ +  Q3POBJ = \      $(B)/client/linux_glimp.o \ -    $(B)/client/linux_snd.o \ -    $(B)/client/sdl_snd.o +    $(B)/client/sdl_glimp.o -  Q3POBJ_SMP=\ -    $(B)/client/unix_main.o \ -    $(B)/client/unix_net.o \ -    $(B)/client/unix_shared.o \ -    $(B)/client/linux_signals.o \ -    $(B)/client/linux_common.o \ -    $(B)/client/linux_qgl.o \ +  Q3POBJ_SMP = \      $(B)/client/linux_glimp_smp.o \ -    $(B)/client/linux_snd.o \ -    $(B)/client/sdl_snd.o - -  ifeq ($(ARCH),i386) -    Q3POBJ += $(B)/client/ftola.o $(B)/client/snapvectora.o $(B)/client/snd_mixa.o $(B)/client/matha.o -    Q3POBJ_SMP += $(B)/client/ftola.o $(B)/client/snapvectora.o -  endif - -endif #SunOS -endif #Linux -endif #darwin -endif #mingw32 -endif #IRIX -endif #FreeBSD +    $(B)/client/sdl_glimp_smp.o +endif -$(B)/$(PLATFORM)tremulous$(BINEXT): $(Q3OBJ) $(Q3POBJ) $(LIBSDLMAIN) +$(B)/tremulous.$(ARCH)$(BINEXT): $(Q3OBJ) $(Q3POBJ) $(LIBSDLMAIN)  	$(CC)  -o $@ $(Q3OBJ) $(Q3POBJ) $(CLIENT_LDFLAGS) $(LDFLAGS) $(LIBSDLMAIN) -$(B)/$(PLATFORM)tremulous-smp$(BINEXT): $(Q3OBJ) $(Q3POBJ_SMP) $(LIBSDLMAIN) +$(B)/tremulous-smp.$(ARCH)$(BINEXT): $(Q3OBJ) $(Q3POBJ_SMP) $(LIBSDLMAIN)  	$(CC)  -o $@ $(Q3OBJ) $(Q3POBJ_SMP) $(CLIENT_LDFLAGS) \  		$(THREAD_LDFLAGS) $(LDFLAGS) $(LIBSDLMAIN) @@ -1110,6 +906,7 @@ $(B)/client/cl_net_chan.o : $(CDIR)/cl_net_chan.c; $(DO_CC)  $(B)/client/cl_parse.o : $(CDIR)/cl_parse.c; $(DO_CC)  $(B)/client/cl_scrn.o : $(CDIR)/cl_scrn.c; $(DO_CC)  $(B)/client/cl_ui.o : $(CDIR)/cl_ui.c; $(DO_CC) +$(B)/client/cl_avi.o : $(CDIR)/cl_avi.c; $(DO_CC)  $(B)/client/snd_adpcm.o : $(CDIR)/snd_adpcm.c; $(DO_CC)  $(B)/client/snd_dma.o : $(CDIR)/snd_dma.c; $(DO_CC)  $(B)/client/snd_mem.o : $(CDIR)/snd_mem.c; $(DO_CC) @@ -1249,7 +1046,6 @@ $(B)/client/irix_glimp_smp.o : $(UDIR)/irix_glimp.c; $(DO_SMP_CC)  $(B)/client/irix_snd.o : $(UDIR)/irix_snd.c; $(DO_CC)  $(B)/client/irix_input.o : $(UDIR)/irix_input.c; $(DO_CC)  $(B)/client/linux_signals.o : $(UDIR)/linux_signals.c; $(DO_CC) $(GL_CFLAGS) -$(B)/client/linux_common.o : $(UDIR)/linux_common.c; $(DO_CC)  $(B)/client/linux_glimp.o : $(UDIR)/linux_glimp.c; $(DO_CC)  $(GL_CFLAGS)  $(B)/client/sdl_glimp.o : $(UDIR)/sdl_glimp.c; $(DO_CC)  $(GL_CFLAGS)  $(B)/client/linux_glimp_smp.o : $(UDIR)/linux_glimp.c; $(DO_SMP_CC)  $(GL_CFLAGS) @@ -1352,7 +1148,6 @@ Q3DOBJ = \    $(B)/ded/l_struct.o \    \    $(B)/ded/linux_signals.o \ -  $(B)/ded/linux_common.o \    $(B)/ded/unix_main.o \    $(B)/ded/unix_net.o \    $(B)/ded/unix_shared.o \ @@ -1376,7 +1171,7 @@ ifeq ($(ARCH),ppc)    endif  endif -$(B)/$(PLATFORM)tremded$(BINEXT): $(Q3DOBJ) +$(B)/tremded.$(ARCH)$(BINEXT): $(Q3DOBJ)  	$(CC) -o $@ $(Q3DOBJ) $(LDFLAGS)  $(B)/ded/sv_bot.o : $(SDIR)/sv_bot.c; $(DO_DED_CC) @@ -1434,7 +1229,6 @@ $(B)/ded/l_script.o : $(BLIBDIR)/l_script.c; $(DO_BOT_CC)  $(B)/ded/l_struct.o : $(BLIBDIR)/l_struct.c; $(DO_BOT_CC)  $(B)/ded/linux_signals.o : $(UDIR)/linux_signals.c; $(DO_DED_CC) -$(B)/ded/linux_common.o : $(UDIR)/linux_common.c; $(DO_DED_CC)  $(B)/ded/unix_main.o : $(UDIR)/unix_main.c; $(DO_DED_CC)  $(B)/ded/unix_net.o : $(UDIR)/unix_net.c; $(DO_DED_CC)  $(B)/ded/unix_shared.o : $(UDIR)/unix_shared.c; $(DO_DED_CC) @@ -1611,11 +1405,11 @@ $(B)/base/qcommon/%.asm: $(CMDIR)/%.c  #############################################################################  copyfiles: build_release -	@if [ ! -d $(COPYDIR)/base ]; then echo "You need to set COPYDIR to where you installed Quake III!"; false; fi -	$(INSTALL) -s -m 0755 $(BR)/$(PLATFORM)tremulous$(BINEXT) $(COPYDIR)/tremulous +	@if [ ! -d $(COPYDIR)/baseq3 ]; then echo "You need to set COPYDIR to where you installed Trem!"; false; fi +	$(INSTALL) -s -m 0755 $(BR)/tremulous.$(ARCH)$(BINEXT) $(COPYDIR)/tremulous.$(ARCH)$(BINEXT) -	@if [ -f $(BR)/$(PLATFORM)tremded$(BINEXT) ]; then \ -		$(INSTALL) -s -m 0755 $(BR)/$(PLATFORM)tremded$(BINEXT) $(COPYDIR)/tremded +	@if [ -f $(BR)/tremded.$(ARCH)$(BINEXT) ]; then \ +		$(INSTALL) -s -m 0755 $(BR)/tremded.$(ARCH)$(BINEXT) $(COPYDIR)/tremded.$(ARCH)$(BINEXT); \  	fi  	-$(MKDIR) -p -m 0755 $(COPYDIR)/base  	$(INSTALL) -s -m 0755 $(BR)/base/cgame$(ARCH).$(SHLIBEXT) \ @@ -1655,6 +1449,12 @@ installer: build_release  D_FILES=$(shell find . -name '*.d') +$(B)/base/vm/vm.d: $(GOBJ) $(CGOBJ) $(UIOBJ) +	-rm -f $@ +	find $(B)/base -iname '*.d' | xargs sed -e 's/\.o/\.asm/g' > $@ + +qvmdeps: $(B)/base/vm/vm.d +  ifneq ($(strip $(D_FILES)),)    include $(D_FILES)  endif diff --git a/src/unix/ftola.s b/src/unix/ftola.s index a84f6aae..2459021b 100644 --- a/src/unix/ftola.s +++ b/src/unix/ftola.s @@ -30,7 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  #include "qasm.h" -#ifdef id386 +#if id386  .data diff --git a/src/unix/linux_common.c b/src/unix/linux_common.c deleted file mode 100644 index d7f31189..00000000 --- a/src/unix/linux_common.c +++ /dev/null @@ -1,347 +0,0 @@ -#if 0 // not used anymore -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. -Copyright (C) 2000-2006 Tim Angus - -This file is part of Tremulous. - -Tremulous 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 2 of the License, -or (at your option) any later version. - -Tremulous 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 Tremulous; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA -=========================================================================== -*/ -/**  - * GAS syntax equivalents of the MSVC asm memory calls in common.c - * - * The following changes have been made to the asm: - * 1. Registers are loaded by the inline asm arguments when possible - * 2. Labels have been changed to local label format (0,1,etc.) to allow inlining - * - * HISTORY: - *	AH - Created on 08 Dec 2000 - */ - -#include <unistd.h>   // AH - for size_t -#include <string.h> - -// bk001207 - we need something under Linux, too. Mac? -#if 1 // defined(C_ONLY) // bk010102 - dedicated? -void Com_Memcpy (void* dest, const void* src, const size_t count) { -  memcpy(dest, src, count); -} - -void Com_Memset (void* dest, const int val, const size_t count) { -  memset(dest, val, count); -} - -#else - -typedef enum { -  PRE_READ,         // prefetch assuming that buffer is used for reading only -  PRE_WRITE,        // prefetch assuming that buffer is used for writing only -  PRE_READ_WRITE    // prefetch assuming that buffer is used for both reading and writing -} e_prefetch; - -void Com_Prefetch (const void *s, const unsigned int bytes, e_prefetch type); - -void _copyDWord (unsigned int* dest, const unsigned int constant, const unsigned int count) { -	// MMX version not used on standard Pentium MMX -	// because the dword version is faster (with -	// proper destination prefetching) -		__asm__ __volatile__ (" \ -			//mov			eax,constant		// eax = val \ -			//mov			edx,dest			// dest \ -			//mov			ecx,count \ -			movd		%%eax, %%mm0 \ -			punpckldq	%%mm0, %%mm0 \ -\ -			// ensure that destination is qword aligned \ -\ -			testl		$7, %%edx				// qword padding?\ -			jz		0f	\ -			movl		%%eax, (%%edx) \ -			decl		%%ecx \ -			addl		$4, %%edx \ -\ -0:			movl		%%ecx, %%ebx				\ -			andl		$0xfffffff0, %%ecx	\ -			jz		2f \ -			jmp		1f \ -			.align 		16 \ -\ -			// funny ordering here to avoid commands \ -			// that cross 32-byte boundaries (the \ -			// [edx+0] version has a special 3-byte opcode... \ -1:			movq		%%mm0, 8(%%edx) \ -			movq		%%mm0, 16(%%edx) \ -			movq		%%mm0, 24(%%edx) \ -			movq		%%mm0, 32(%%edx) \ -			movq		%%mm0, 40(%%edx) \ -			movq		%%mm0, 48(%%edx) \ -			movq		%%mm0, 56(%%edx) \ -			movq		%%mm0, (%%edx)\ -			addl		$64, %%edx \ -			subl		$16, %%ecx \ -			jnz		1b \ -2:	\ -			movl		%%ebx, %%ecx				// ebx = cnt \ -			andl		$0xfffffff0, %%ecx				// ecx = cnt&~15 \ -			subl		%%ecx, %%ebx \ -			jz		6f \ -			cmpl		$8, %%ebx \ -			jl		3f \ -\ -			movq		%%mm0, (%%edx) \ -			movq		%%mm0, 8(%%edx) \ -			movq		%%mm0, 16(%%edx) \ -			movq		%%mm0, 24(%%edx) \ -			addl		$32, %%edx \ -			subl		$8, %%ebx \ -			jz		6f \ -\ -3:			cmpl		$4, %%ebx \ -			jl		4f \ -			\ -			movq		%%mm0, (%%edx) \ -			movq		%%mm0, 8(%%edx) \ -			addl		$16, %%edx \ -			subl		$4, %%ebx \ -\ -4:			cmpl		$2, %%ebx \ -			jl		5f \ -			movq		%%mm0, (%%edx) \ -			addl		$8, %%edx \ -			subl		$2, %%ebx \ -\ -5:			cmpl		$1, %%ebx \ -			jl		6f \ -			movl		%%eax, (%%edx) \ -6: \ -			emms \ -	" -	: : "a" (constant), "c" (count), "d" (dest) -	: "%ebx", "%edi", "%esi", "cc", "memory"); -} - -// optimized memory copy routine that handles all alignment -// cases and block sizes efficiently -void Com_Memcpy (void* dest, const void* src, const size_t count) { -	Com_Prefetch (src, count, PRE_READ); -	__asm__ __volatile__ (" \ -		pushl		%%edi \ -		pushl		%%esi \ -		//mov		ecx,count \ -		cmpl		$0, %%ecx						// count = 0 check (just to be on the safe side) \ -		je		6f \ -		//mov		edx,dest \ -		movl		%0, %%ebx \ -		cmpl		$32, %%ecx						// padding only? \ -		jl		1f \ -\ -		movl		%%ecx, %%edi					\ -		andl		$0xfffffe00, %%edi					// edi = count&~31 \ -		subl		$32, %%edi \ -\ -		.align 16 \ -0: \ -		movl		(%%ebx, %%edi, 1), %%eax \ -		movl		4(%%ebx, %%edi, 1), %%esi \ -		movl		%%eax, (%%edx, %%edi, 1) \ -		movl		%%esi, 4(%%edx, %%edi, 1) \ -		movl		8(%%ebx, %%edi, 1), %%eax \ -		movl		12(%%ebx, %%edi, 1), %%esi \ -		movl		%%eax, 8(%%edx, %%edi, 1) \ -		movl		%%esi, 12(%%edx, %%edi, 1) \ -		movl		16(%%ebx, %%edi, 1), %%eax \ -		movl		20(%%ebx, %%edi, 1), %%esi \ -		movl		%%eax, 16(%%edx, %%edi, 1) \ -		movl		%%esi, 20(%%edx, %%edi, 1) \ -		movl		24(%%ebx, %%edi, 1), %%eax \ -		movl		28(%%ebx, %%edi, 1), %%esi \ -		movl		%%eax, 24(%%edx, %%edi, 1) \ -		movl		%%esi, 28(%%edx, %%edi, 1) \ -		subl		$32, %%edi \ -		jge		0b \ -		\ -		movl		%%ecx, %%edi \ -		andl		$0xfffffe00, %%edi \ -		addl		%%edi, %%ebx					// increase src pointer \ -		addl		%%edi, %%edx					// increase dst pointer \ -		andl		$31, %%ecx					// new count \ -		jz		6f					// if count = 0, get outta here \ -\ -1: \ -		cmpl		$16, %%ecx \ -		jl		2f \ -		movl		(%%ebx), %%eax \ -		movl		%%eax, (%%edx) \ -		movl		4(%%ebx), %%eax \ -		movl		%%eax, 4(%%edx) \ -		movl		8(%%ebx), %%eax \ -		movl		%%eax, 8(%%edx) \ -		movl		12(%%ebx), %%eax \ -		movl		%%eax, 12(%%edx) \ -		subl		$16, %%ecx \ -		addl		$16, %%ebx \ -		addl		$16, %%edx \ -2: \ -		cmpl		$8, %%ecx \ -		jl		3f \ -		movl		(%%ebx), %%eax \ -		movl		%%eax, (%%edx) \ -		movl		4(%%ebx), %%eax \ -		subl		$8, %%ecx \ -		movl		%%eax, 4(%%edx) \ -		addl		$8, %%ebx \ -		addl		$8, %%edx \ -3: \ -		cmpl		$4, %%ecx \ -		jl		4f \ -		movl		(%%ebx), %%eax	// here 4-7 bytes \ -		addl		$4, %%ebx \ -		subl		$4, %%ecx \ -		movl		%%eax, (%%edx) \ -		addl		$4, %%edx \ -4:							// 0-3 remaining bytes \ -		cmpl		$2, %%ecx \ -		jl		5f \ -		movw		(%%ebx), %%ax	// two bytes \ -		cmpl		$3, %%ecx				// less than 3? \ -		movw		%%ax, (%%edx) \ -		jl		6f \ -		movb		2(%%ebx), %%al	// last byte \ -		movb		%%al, 2(%%edx) \ -		jmp		6f \ -5: \ -		cmpl		$1, %%ecx \ -		jl		6f \ -		movb		(%%ebx), %%al \ -		movb		%%al, (%%edx) \ -6: \ -		popl		%%esi \ -		popl		%%edi \ -	" -	: : "m" (src), "d" (dest), "c" (count) -	: "%eax", "%ebx", "%edi", "%esi", "cc", "memory"); -} - -void Com_Memset (void* dest, const int val, const size_t count) -{ -	unsigned int fillval; - -	if (count < 8) -	{ -		__asm__ __volatile__ (" \ -			//mov		edx,dest \ -			//mov		eax, val \ -			movb		%%al, %%ah \ -			movl		%%eax, %%ebx \ -			andl		$0xffff, %%ebx \ -			shll		$16, %%eax \ -			addl		%%ebx, %%eax	// eax now contains pattern \ -			//mov		ecx,count \ -			cmpl		$4, %%ecx \ -			jl		0f \ -			movl		%%eax, (%%edx)	// copy first dword \ -			addl		$4, %%edx \ -			subl		$4, %%ecx \ -	0:		cmpl		$2, %%ecx \ -			jl		1f \ -			movw		%%ax, (%%edx)	// copy 2 bytes \ -			addl		$2, %%edx \ -			subl		$2, %%ecx \ -	1:		cmpl		$0, %%ecx \ -			je		2f \ -			movb		%%al, (%%edx)	// copy single byte \ -	2:		 \ -		" -		: : "d" (dest), "a" (val), "c" (count) -		: "%ebx", "%edi", "%esi", "cc", "memory"); -		 -		return; -	} - -	fillval = val; -	 -	fillval = fillval|(fillval<<8); -	fillval = fillval|(fillval<<16);		// fill dword with 8-bit pattern - -	_copyDWord ((unsigned int*)(dest),fillval, count/4); -	 -	__asm__ __volatile__ ("     		// padding of 0-3 bytes \ -		//mov		ecx,count \ -		movl		%%ecx, %%eax \ -		andl		$3, %%ecx \ -		jz		1f \ -		andl		$0xffffff00, %%eax \ -		//mov		ebx,dest \ -		addl		%%eax, %%edx \ -		movl		%0, %%eax \ -		cmpl		$2, %%ecx \ -		jl		0f \ -		movw		%%ax, (%%edx) \ -		cmpl		$2, %%ecx \ -		je		1f					\ -		movb		%%al, 2(%%edx)		\ -		jmp		1f \ -0:		\ -		cmpl		$0, %%ecx\ -		je		1f\ -		movb		%%al, (%%edx)\ -1:	\ -	" -	: : "m" (fillval), "c" (count), "d" (dest) -	: "%eax", "%ebx", "%edi", "%esi", "cc", "memory");	 -} - -void Com_Prefetch (const void *s, const unsigned int bytes, e_prefetch type) -{ -	// write buffer prefetching is performed only if -	// the processor benefits from it. Read and read/write -	// prefetching is always performed. - -	switch (type) -	{ -		case PRE_WRITE : break; -		case PRE_READ: -		case PRE_READ_WRITE: - -		__asm__ __volatile__ ("\ -			//mov		ebx,s\ -			//mov		ecx,bytes\ -			cmpl		$4096, %%ecx				// clamp to 4kB\ -			jle		0f\ -			movl		$4096, %%ecx\ -	0:\ -			addl		$0x1f, %%ecx\ -			shrl		$5, %%ecx					// number of cache lines\ -			jz		2f\ -			jmp		1f\ -\ -			.align 16\ -	1:		testb		%%al, (%%edx)\ -			addl		$32, %%edx\ -			decl		%%ecx\ -			jnz		1b\ -	2:\ -		" -		: : "d" (s), "c" (bytes) -		: "%eax", "%ebx", "%edi", "%esi", "memory", "cc"); -		 -		break; -	} -} - -#endif -#endif  | 
