From 7d96b51fbc8b0df8ebf348de2aa5f2058254ed93 Mon Sep 17 00:00:00 2001
From: Tim Angus <tim@ngus.net>
Date: Mon, 9 Jan 2006 02:16:46 +0000
Subject: * Merged ioq3-468

---
 src/client/cl_avi.c        |  10 +-
 src/client/cl_main.c       |   8 +-
 src/client/client.h        |   2 +-
 src/client/snd_codec.c     |   4 +-
 src/client/snd_codec.h     |   1 +
 src/client/snd_codec_ogg.c | 465 +++++++++++++++++++++++++++++++++++++++++++++
 src/client/snd_dma.c       |   2 +-
 src/game/g_mover.c         |   2 +-
 src/qcommon/vm_x86_64.c    |   5 +-
 src/unix/Makefile          |  40 +++-
 10 files changed, 514 insertions(+), 25 deletions(-)
 create mode 100644 src/client/snd_codec_ogg.c

diff --git a/src/client/cl_avi.c b/src/client/cl_avi.c
index 4a372d8b..178260be 100644
--- a/src/client/cl_avi.c
+++ b/src/client/cl_avi.c
@@ -332,9 +332,9 @@ qboolean CL_OpenAVIForWriting( const char *fileName )
   Com_Memset( &afd, 0, sizeof( aviFileData_t ) );
 
   // Don't start if a framerate has not been chosen
-  if( cl_avidemo->integer <= 0 )
+  if( cl_aviFrameRate->integer <= 0 )
   {
-    Com_Printf( S_COLOR_RED "cl_avidemo must be >= 1\n" );
+    Com_Printf( S_COLOR_RED "cl_aviFrameRate must be >= 1\n" );
     return qfalse;
   }
 
@@ -349,7 +349,7 @@ qboolean CL_OpenAVIForWriting( const char *fileName )
 
   Q_strncpyz( afd.fileName, fileName, MAX_QPATH );
 
-  afd.frameRate = cl_avidemo->integer;
+  afd.frameRate = cl_aviFrameRate->integer;
   afd.framePeriod = (int)( 1000000.0f / afd.frameRate );
   afd.width = cls.glconfig.vidWidth;
   afd.height = cls.glconfig.vidHeight;
@@ -375,7 +375,7 @@ qboolean CL_OpenAVIForWriting( const char *fileName )
     while( ( afd.a.rate % suggestRate ) && suggestRate >= 1 )
       suggestRate--;
 
-    Com_Printf( S_COLOR_YELLOW "WARNING: cl_avidemo is not a divisor "
+    Com_Printf( S_COLOR_YELLOW "WARNING: cl_aviFrameRate is not a divisor "
         "of the audio rate, suggest %d\n", suggestRate );
   }
 
@@ -484,7 +484,7 @@ void CL_WriteAVIAudioFrame( const byte *pcmBuffer, int size )
   bytesInBuffer += size;
 
   // Only write if we have a frame's worth of audio
-  if( bytesInBuffer >= (int)ceil( afd.a.rate / cl_avidemo->value ) *
+  if( bytesInBuffer >= (int)ceil( afd.a.rate / cl_aviFrameRate->value ) *
         afd.a.sampleSize )
   {
     int   chunkOffset = afd.fileSize - afd.moviOffset - 8;
diff --git a/src/client/cl_main.c b/src/client/cl_main.c
index a00f901e..3f2e1152 100644
--- a/src/client/cl_main.c
+++ b/src/client/cl_main.c
@@ -45,7 +45,7 @@ cvar_t	*cl_shownet;
 cvar_t	*cl_showSend;
 cvar_t	*cl_timedemo;
 cvar_t	*cl_autoRecordDemo;
-cvar_t	*cl_avidemo;
+cvar_t	*cl_aviFrameRate;
 cvar_t	*cl_aviMotionJpeg;
 cvar_t	*cl_forceavidemo;
 
@@ -1974,13 +1974,13 @@ void CL_Frame ( int msec ) {
 	}
 
 	// if recording an avi, lock to a fixed fps
-	if ( CL_VideoRecording( ) && cl_avidemo->integer && msec) {
+	if ( CL_VideoRecording( ) && cl_aviFrameRate->integer && msec) {
 		// save the current screen
 		if ( cls.state == CA_ACTIVE || cl_forceavidemo->integer) {
 			CL_TakeVideoFrame( );
 
 			// fixed time for next frame'
-			msec = (int)ceil( (1000.0f / cl_avidemo->value) * com_timescale->value );
+			msec = (int)ceil( (1000.0f / cl_aviFrameRate->value) * com_timescale->value );
 			if (msec == 0) {
 				msec = 1;
 			}
@@ -2362,7 +2362,7 @@ void CL_Init( void ) {
 
 	cl_timedemo = Cvar_Get ("timedemo", "0", 0);
 	cl_autoRecordDemo = Cvar_Get ("cl_autoRecordDemo", "0", CVAR_ARCHIVE);
-	cl_avidemo = Cvar_Get ("cl_avidemo", "25", CVAR_ARCHIVE);
+	cl_aviFrameRate = Cvar_Get ("cl_aviFrameRate", "25", CVAR_ARCHIVE);
 	cl_aviMotionJpeg = Cvar_Get ("cl_aviMotionJpeg", "1", CVAR_ARCHIVE);
 	cl_forceavidemo = Cvar_Get ("cl_forceavidemo", "0", 0);
 
diff --git a/src/client/client.h b/src/client/client.h
index 1c4fa198..fb1ecea1 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -343,7 +343,7 @@ extern	cvar_t	*m_side;
 extern	cvar_t	*m_filter;
 
 extern	cvar_t	*cl_timedemo;
-extern	cvar_t	*cl_avidemo;
+extern	cvar_t	*cl_aviFrameRate;
 extern	cvar_t	*cl_aviMotionJpeg;
 
 extern	cvar_t	*cl_activeAction;
diff --git a/src/client/snd_codec.c b/src/client/snd_codec.c
index 338d0306..e1c6bb47 100644
--- a/src/client/snd_codec.c
+++ b/src/client/snd_codec.c
@@ -192,9 +192,10 @@ snd_stream_t *S_CodecUtilOpen(const char *filename, snd_codec_t *codec)
 {
 	snd_stream_t *stream;
 	fileHandle_t hnd;
+	int length;
 
 	// Try to open the file
-	FS_FOpenFileRead(filename, &hnd, qtrue);
+	length = FS_FOpenFileRead(filename, &hnd, qtrue);
 	if(!hnd)
 	{
 		Com_Printf("Can't read sound file %s\n", filename);
@@ -212,6 +213,7 @@ snd_stream_t *S_CodecUtilOpen(const char *filename, snd_codec_t *codec)
 	// Copy over, return
 	stream->codec = codec;
 	stream->file = hnd;
+	stream->length = length;
 	return stream;
 }
 
diff --git a/src/client/snd_codec.h b/src/client/snd_codec.h
index 74ac77e9..582e65ef 100644
--- a/src/client/snd_codec.h
+++ b/src/client/snd_codec.h
@@ -45,6 +45,7 @@ typedef struct snd_stream_s
 	snd_codec_t *codec;
 	fileHandle_t file;
 	snd_info_t info;
+	int length;
 	int pos;
 	void *ptr;
 } snd_stream_t;
diff --git a/src/client/snd_codec_ogg.c b/src/client/snd_codec_ogg.c
new file mode 100644
index 00000000..20462fcb
--- /dev/null
+++ b/src/client/snd_codec_ogg.c
@@ -0,0 +1,465 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
+Copyright (C) 2005-2006 Joerg Dietrich <dietrich_joerg@gmx.de>
+
+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
+===========================================================================
+*/
+
+// OGG support is enabled by this define
+#ifdef USE_CODEC_VORBIS
+
+// includes for the Q3 sound system
+#include "client.h"
+#include "snd_codec.h"
+
+// includes for the OGG codec
+#include <errno.h>
+#include <vorbis/vorbisfile.h>
+
+// The OGG codec can return the samples in a number of different formats,
+// we use the standard signed short format.
+#define OGG_SAMPLEWIDTH 2
+
+// Q3 OGG codec
+snd_codec_t ogg_codec =
+{
+	".ogg",
+	S_OGG_CodecLoad,
+	S_OGG_CodecOpenStream,
+	S_OGG_CodecReadStream,
+	S_OGG_CodecCloseStream,
+	NULL
+};
+
+// callbacks for vobisfile
+
+// fread() replacement
+size_t S_OGG_Callback_read(void *ptr, size_t size, size_t nmemb, void *datasource)
+{
+	snd_stream_t *stream;
+	int byteSize = 0;
+	int bytesRead = 0;
+	size_t nMembRead = 0;
+
+	// check if input is valid
+	if(!ptr)
+	{
+		errno = EFAULT; 
+		return 0;
+	}
+	
+	if(!(size && nmemb))
+	{
+		// It's not an error, caller just wants zero bytes!
+		errno = 0;
+		return 0;
+	}
+ 
+	if(!datasource)
+	{
+		errno = EBADF; 
+		return 0;
+	}
+	
+	// we use a snd_stream_t in the generic pointer to pass around
+	stream = (snd_stream_t *) datasource;
+
+	// FS_Read does not support multi-byte elements
+	byteSize = nmemb * size;
+
+	// read it with the Q3 function FS_Read()
+	bytesRead = FS_Read(ptr, byteSize, stream->file);
+
+	// update the file position
+	stream->pos += bytesRead;
+
+	// this function returns the number of elements read not the number of bytes
+	nMembRead = bytesRead / size;
+
+	// even if the last member is only read partially
+	// it is counted as a whole in the return value	
+	if(bytesRead % size)
+	{
+		nMembRead++;
+	}
+	
+	return nMembRead;
+}
+
+// fseek() replacement
+int S_OGG_Callback_seek(void *datasource, ogg_int64_t offset, int whence)
+{
+	snd_stream_t *stream;
+	int retVal = 0;
+
+	// check if input is valid
+	if(!datasource)
+	{
+		errno = EBADF; 
+		return -1;
+	}
+
+	// snd_stream_t in the generic pointer
+	stream = (snd_stream_t *) datasource;
+
+	// we must map the whence to its Q3 counterpart
+	switch(whence)
+	{
+		case SEEK_SET :
+		{
+			// set the file position in the actual file with the Q3 function
+			retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_SET);
+
+			// something has gone wrong, so we return here
+			if(!(retVal == 0))
+			{
+			 return retVal;
+			}
+
+			// keep track of file position
+			stream->pos = (int) offset;
+			break;
+		}
+  
+		case SEEK_CUR :
+		{
+			// set the file position in the actual file with the Q3 function
+			retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_CUR);
+
+			// something has gone wrong, so we return here
+			if(!(retVal == 0))
+			{
+			 return retVal;
+			}
+
+			// keep track of file position
+			stream->pos += (int) offset;
+			break;
+		}
+ 
+		case SEEK_END :
+		{
+			// Quake 3 seems to have trouble with FS_SEEK_END 
+			// so we use the file length and FS_SEEK_SET
+
+			// set the file position in the actual file with the Q3 function
+			retVal = FS_Seek(stream->file, (long) stream->length + (long) offset, FS_SEEK_SET);
+
+			// something has gone wrong, so we return here
+			if(!(retVal == 0))
+			{
+			 return retVal;
+			}
+
+			// keep track of file position
+			stream->pos = stream->length + (int) offset;
+			break;
+		}
+  
+		default :
+		{
+			// unknown whence, so we return an error
+			errno = EINVAL;
+			return -1;
+		}
+	}
+
+	// stream->pos shouldn't be smaller than zero or bigger than the filesize
+	stream->pos = (stream->pos < 0) ? 0 : stream->pos;
+	stream->pos = (stream->pos > stream->length) ? stream->length : stream->pos;
+
+	return 0;
+}
+
+// fclose() replacement
+int S_OGG_Callback_close(void *datasource)
+{
+	// we do nothing here and close all things manually in S_OGG_CodecCloseStream()
+	return 0;
+}
+
+// ftell() replacement
+long S_OGG_Callback_tell(void *datasource)
+{
+	// check if input is valid
+	if(!datasource)
+	{
+		errno = EBADF; 
+		return -1;
+	}
+
+	// we keep track of the file position in stream->pos
+	return (long) (((snd_stream_t *) datasource) -> pos);
+}
+
+// the callback structure
+const ov_callbacks S_OGG_Callbacks =
+{
+ &S_OGG_Callback_read,
+ &S_OGG_Callback_seek,
+ &S_OGG_Callback_close,
+ &S_OGG_Callback_tell
+};
+
+/*
+=================
+S_OGG_CodecOpenStream
+=================
+*/
+snd_stream_t *S_OGG_CodecOpenStream(const char *filename)
+{
+	snd_stream_t *stream;
+
+	// OGG codec control structure
+	OggVorbis_File *vf;
+
+	// some variables used to get informations about the OGG 
+	vorbis_info *OGGInfo;
+	ogg_int64_t numSamples;
+
+	// check if input is valid
+	if(!filename)
+	{
+		return NULL;
+	}
+
+	// Open the stream
+	stream = S_CodecUtilOpen(filename, &ogg_codec);
+	if(!stream)
+	{
+		return NULL;
+	}
+
+	// alloctate the OggVorbis_File
+	vf = Z_Malloc(sizeof(OggVorbis_File));
+	if(!vf)
+	{
+		S_CodecUtilClose(stream);
+
+		return NULL;
+	}
+
+	// open the codec with our callbacks and stream as the generic pointer
+	if(ov_open_callbacks(stream, vf, NULL, 0, S_OGG_Callbacks) != 0)
+	{
+		Z_Free(vf);
+
+		S_CodecUtilClose(stream);
+
+		return NULL;
+	}
+
+	// the stream must be seekable
+	if(!ov_seekable(vf))
+	{
+		ov_clear(vf);
+
+		Z_Free(vf);
+
+		S_CodecUtilClose(stream);
+
+		return NULL;
+	}
+ 
+	// we only support OGGs with one substream
+	if(ov_streams(vf) != 1)
+	{
+		ov_clear(vf);
+
+		Z_Free(vf);
+
+		S_CodecUtilClose(stream);
+
+		return NULL;  
+	}
+
+	// get the info about channels and rate
+	OGGInfo = ov_info(vf, 0);
+	if(!OGGInfo)
+	{
+		ov_clear(vf);
+
+		Z_Free(vf);
+
+		S_CodecUtilClose(stream);
+
+		return NULL;  
+	}
+
+	// get the number of sample-frames in the OGG
+	numSamples = ov_pcm_total(vf, 0);
+
+	// fill in the info-structure in the stream
+	stream->info.rate = OGGInfo->rate;
+	stream->info.width = OGG_SAMPLEWIDTH;
+	stream->info.channels = OGGInfo->channels;
+	stream->info.samples = numSamples;
+	stream->info.size = stream->info.samples * stream->info.channels * stream->info.width;
+	stream->info.dataofs = 0;
+
+	// We use stream->pos for the file pointer in the compressed ogg file 
+	stream->pos = 0;
+	
+	// We use the generic pointer in stream for the OGG codec control structure
+	stream->ptr = vf;
+
+	return stream;
+}
+
+/*
+=================
+S_OGG_CodecCloseStream
+=================
+*/
+void S_OGG_CodecCloseStream(snd_stream_t *stream)
+{
+	// check if input is valid
+	if(!stream)
+	{
+		return;
+	}
+	
+	// let the OGG codec cleanup its stuff
+	ov_clear((OggVorbis_File *) stream->ptr);
+
+	// free the OGG codec control struct
+	Z_Free(stream->ptr);
+
+	// close the stream
+	S_CodecUtilClose(stream);
+}
+
+/*
+=================
+S_OGG_CodecReadStream
+=================
+*/
+int S_OGG_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
+{
+	// buffer handling
+	int bytesRead, bytesLeft, c;
+	char *bufPtr;
+	
+	// Bitstream for the decoder
+	int BS = 0;
+
+	// check if input is valid
+	if(!(stream && buffer))
+	{
+		return 0;
+	}
+
+	if(bytes <= 0)
+	{
+		return 0;
+	}
+
+	bytesRead = 0;
+	bytesLeft = bytes;
+	bufPtr = buffer;
+
+	// cycle until we have the requested or all available bytes read
+	while(-1)
+	{
+		// read some bytes from the OGG codec
+		c = ov_read((OggVorbis_File *) stream->ptr, bufPtr, bytesLeft, 0, OGG_SAMPLEWIDTH, 1, &BS);
+		
+		// no more bytes are left
+		if(c <= 0)
+		{
+			break;
+		}
+
+		bytesRead += c;
+		bytesLeft -= c;
+		bufPtr += c;
+  
+		// we have enough bytes
+		if(bytesLeft <= 0)
+		{
+			break;
+		}
+	}
+
+	return bytesRead;
+}
+
+/*
+=====================================================================
+S_OGG_CodecLoad
+
+We handle S_OGG_CodecLoad as a special case of the streaming functions 
+where we read the whole stream at once.
+======================================================================
+*/
+void *S_OGG_CodecLoad(const char *filename, snd_info_t *info)
+{
+	snd_stream_t *stream;
+	unsigned char *buffer;
+	int bytesRead;
+	
+	// check if input is valid
+	if(!(filename && info))
+	{
+		return NULL;
+	}
+	
+	// open the file as a stream
+	stream = S_OGG_CodecOpenStream(filename);
+	if(!stream)
+	{
+		return NULL;
+	}
+	
+	// copy over the info
+	info->rate = stream->info.rate;
+	info->width = stream->info.width;
+	info->channels = stream->info.channels;
+	info->samples = stream->info.samples;
+	info->size = stream->info.size;
+	info->dataofs = stream->info.dataofs;
+
+	// allocate a buffer
+	// this buffer must be free-ed by the caller of this function
+    	buffer = Z_Malloc(info->size);
+	if(!buffer)
+	{
+		S_OGG_CodecCloseStream(stream);
+	
+		return NULL;	
+	}
+
+	// fill the buffer
+	bytesRead = S_OGG_CodecReadStream(stream, info->size, buffer);
+	
+	// we don't even have read a single byte
+	if(bytesRead <= 0)
+	{
+		S_OGG_CodecCloseStream(stream);
+	
+		return NULL;	
+	}
+
+	S_OGG_CodecCloseStream(stream);
+	
+	return buffer;
+}
+
+#endif // USE_CODEC_VORBIS
diff --git a/src/client/snd_dma.c b/src/client/snd_dma.c
index d51a4b85..ee57f6f2 100644
--- a/src/client/snd_dma.c
+++ b/src/client/snd_dma.c
@@ -1142,7 +1142,7 @@ void S_GetSoundtime(void)
 
 	if( CL_VideoRecording( ) )
 	{
-		s_soundtime += (int)ceil( dma.speed / cl_avidemo->value );
+		s_soundtime += (int)ceil( dma.speed / cl_aviFrameRate->value );
 		return;
 	}
 
diff --git a/src/game/g_mover.c b/src/game/g_mover.c
index 0c060c7b..8f7de418 100644
--- a/src/game/g_mover.c
+++ b/src/game/g_mover.c
@@ -1937,7 +1937,7 @@ void SP_func_button( gentity_t *ent )
   float   lip;
   char    *s;
 
-  G_SpawnString( "sound1to2", "sound/movers/switches/butn2.wav", &s );
+  G_SpawnString( "sound1to2", "sound/movers/switches/button1.wav", &s );
   ent->sound1to2 = G_SoundIndex( s );
 
   if( !ent->speed )
diff --git a/src/qcommon/vm_x86_64.c b/src/qcommon/vm_x86_64.c
index e8545b9f..23f87c30 100644
--- a/src/qcommon/vm_x86_64.c
+++ b/src/qcommon/vm_x86_64.c
@@ -386,12 +386,11 @@ static int doas(char* in, char* out, unsigned char** compiledcode)
 
 	if((*compiledcode = (unsigned char*)buf))
 	{
-#ifdef VM_X86_64_STANDALONE // no idea why
-		if(mprotect(buf, allocsize, PROT_READ|PROT_EXEC) == -1)
+		// need to be able to exec code
+		if(mprotect(buf, allocsize, PROT_READ|PROT_WRITE|PROT_EXEC) == -1)
 		{
 			Com_Error(ERR_FATAL, "mprotect failed on %p+%x: %s\n", buf, allocsize, strerror(errno));
 		}
-#endif
 		return size;
 	}
 
diff --git a/src/unix/Makefile b/src/unix/Makefile
index 4769b075..29301edb 100644
--- a/src/unix/Makefile
+++ b/src/unix/Makefile
@@ -92,6 +92,10 @@ ifndef USE_OPENAL_DLOPEN
 USE_OPENAL_DLOPEN=0
 endif
 
+ifndef USE_CODEC_VORBIS
+USE_CODEC_VORBIS=0
+endif
+
 ifndef USE_LOCAL_HEADERS
 USE_LOCAL_HEADERS=1
 endif
@@ -158,6 +162,10 @@ ifeq ($(PLATFORM),linux)
     endif
   endif
 
+  ifeq ($(USE_CODEC_VORBIS),1)
+    BASE_CFLAGS += -DUSE_CODEC_VORBIS=1
+  endif
+
   ifeq ($(USE_SDL),1)
     BASE_CFLAGS += -DUSE_SDL_VIDEO=1 -DUSE_SDL_SOUND=1 $(shell sdl-config --cflags)
     GL_CFLAGS =
@@ -216,6 +224,10 @@ ifeq ($(PLATFORM),linux)
     endif
   endif
 
+  ifeq ($(USE_CODEC_VORBIS),1)
+    CLIENT_LDFLAGS += -lvorbisfile -lvorbis -logg
+  endif
+
   ifeq ($(ARCH),i386)
     # linux32 make ...
     BASE_CFLAGS += -m32
@@ -247,6 +259,10 @@ ifeq ($(PLATFORM),darwin)
     endif
   endif
 
+  ifeq ($(USE_CODEC_VORBIS),1)
+    BASE_CFLAGS += -DUSE_CODEC_VORBIS=1
+  endif
+
   ifeq ($(USE_SDL),1)
     BASE_CFLAGS += -DUSE_SDL_VIDEO=1 -DUSE_SDL_SOUND=1 -D_THREAD_SAFE=1 -I../SDL12/include
     GL_CFLAGS =
@@ -303,6 +319,10 @@ ifeq ($(PLATFORM),darwin)
     endif
   endif
 
+  ifeq ($(USE_CODEC_VORBIS),1)
+    CLIENT_LDFLAGS += -lvorbisfile -lvorbis -logg
+  endif
+
 else # ifeq darwin
 
 
@@ -323,6 +343,10 @@ ifeq ($(PLATFORM),mingw32)
     BASE_CFLAGS += -DUSE_OPENAL=1 -DUSE_OPENAL_DLOPEN=1
   endif
 
+  ifeq ($(USE_CODEC_VORBIS),1)
+    BASE_CFLAGS += -DUSE_CODEC_VORBIS=1
+  endif
+
   GL_CFLAGS =
   MINGW_CFLAGS = -DDONT_TYPEDEF_INT32
 
@@ -342,6 +366,10 @@ ifeq ($(PLATFORM),mingw32)
   LDFLAGS= -mwindows -lwsock32 -lgdi32 -lwinmm -lole32
   CLIENT_LDFLAGS=
 
+  ifeq ($(USE_CODEC_VORBIS),1)
+    CLIENT_LDFLAGS += -lvorbisfile -lvorbis -logg
+  endif
+
   ifeq ($(ARCH),x86)
     # build 32bit
     BASE_CFLAGS += -m32
@@ -701,6 +729,7 @@ Q3OBJ = \
   $(B)/client/snd_main.o \
   $(B)/client/snd_codec.o \
   $(B)/client/snd_codec_wav.o \
+  $(B)/client/snd_codec_ogg.o \
   \
   $(B)/client/qal.o \
   $(B)/client/snd_openal.o \
@@ -828,13 +857,6 @@ ifeq ($(ARCH),x86)
 endif
 ifeq ($(ARCH),x86_64)
   Q3OBJ += $(B)/client/vm_x86_64.o
-
-  #FIXME: why do these need to be here?
-  Q3OBJ += \
-    $(B)/client/snd_mixa.o \
-    $(B)/client/matha.o \
-    $(B)/client/ftola.o \
-    $(B)/client/snapvectora.o
 endif
 
 ifeq ($(ARCH),ppc)
@@ -920,6 +942,7 @@ $(B)/client/snd_wavelet.o : $(CDIR)/snd_wavelet.c; $(DO_CC)
 $(B)/client/snd_main.o : $(CDIR)/snd_main.c; $(DO_CC)
 $(B)/client/snd_codec.o : $(CDIR)/snd_codec.c; $(DO_CC)
 $(B)/client/snd_codec_wav.o : $(CDIR)/snd_codec_wav.c; $(DO_CC)
+$(B)/client/snd_codec_ogg.o : $(CDIR)/snd_codec_ogg.c; $(DO_CC)
 
 $(B)/client/qal.o : $(CDIR)/qal.c; $(DO_CC)
 $(B)/client/snd_openal.o : $(CDIR)/snd_openal.c; $(DO_CC)
@@ -1454,8 +1477,7 @@ 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' > $@
+	cat $(^:%.o=%.d) | sed -e 's/\.o/\.asm/g' > $@
 
 qvmdeps: $(B)/base/vm/vm.d
 
-- 
cgit