Initial commit.
This commit is contained in:
490
code/client/BinkVideo.cpp
Normal file
490
code/client/BinkVideo.cpp
Normal file
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* This version of BinkVideo.cpp now ONLY works on Xbox.
|
||||
* GCN support is hosed.
|
||||
*/
|
||||
#include "snd_local_console.h"
|
||||
#include "../renderer/tr_local.h"
|
||||
#include "BinkVideo.h"
|
||||
#include "RAD.h"
|
||||
#include "../win32/xbox_texture_man.h"
|
||||
#include <xgraphics.h>
|
||||
|
||||
#include "../client/client.h"
|
||||
|
||||
char *binkSndMem = NULL;
|
||||
|
||||
// Taste the hackery!
|
||||
extern void *BonePoolTempAlloc( unsigned long size );
|
||||
extern void BonePoolTempFree( void *p );
|
||||
extern void *TempAlloc( unsigned long size );
|
||||
extern void TempFree( void );
|
||||
|
||||
extern void SP_DrawSPLoadScreen( void );
|
||||
|
||||
// Allocation wrappers, that go to our static 2.5MB buffer:
|
||||
static void PTR4* RADEXPLINK AllocWrapper(U32 size)
|
||||
{
|
||||
// Give bink pre-initialized sound mem on xbox
|
||||
if(size == XBOX_BINK_SND_MEM) {
|
||||
return binkSndMem;
|
||||
}
|
||||
|
||||
return BinkVideo::Allocate(size);
|
||||
}
|
||||
|
||||
static void RADEXPLINK FreeWrapper(void PTR4* ptr)
|
||||
{
|
||||
BinkVideo::Free(ptr);
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
BinkVideo
|
||||
*********/
|
||||
BinkVideo::BinkVideo()
|
||||
{
|
||||
bink = NULL;
|
||||
buffer = NULL;
|
||||
x1 = 0.0f;
|
||||
y1 = 0.0f;
|
||||
x2 = 0.0f;
|
||||
y2 = 0.0f;
|
||||
status = NS_BV_STOPPED;
|
||||
looping = false;
|
||||
alpha = false;
|
||||
initialized = false;
|
||||
loadScreenOnStop = false;
|
||||
|
||||
Image[0].surface = NULL;
|
||||
Image[0].texture = NULL;
|
||||
Image[1].surface = NULL;
|
||||
Image[1].texture = NULL;
|
||||
|
||||
stopNextFrame = false;
|
||||
}
|
||||
|
||||
/*********
|
||||
~BinkVideo
|
||||
*********/
|
||||
BinkVideo::~BinkVideo()
|
||||
{
|
||||
Free(buffer);
|
||||
BinkClose(bink);
|
||||
}
|
||||
|
||||
/*********
|
||||
AllocateXboxMem
|
||||
Pre-Allocates sound memory for xbox to avoid fragmenting
|
||||
*********/
|
||||
void BinkVideo::AllocateXboxMem(void)
|
||||
{
|
||||
// binkSndMem = (char*)Allocate(XBOX_BINK_SND_MEM);
|
||||
// Force the sound memory to come from the Zone:
|
||||
binkSndMem = (char *) Z_Malloc(XBOX_BINK_SND_MEM, TAG_BINK, qfalse, 32);
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/*********
|
||||
FreeXboxMem
|
||||
*********/
|
||||
void BinkVideo::FreeXboxMem(void)
|
||||
{
|
||||
initialized = false;
|
||||
Z_Free(binkSndMem);
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
Start
|
||||
Opens a bink file and gets it ready to play
|
||||
*********/
|
||||
bool BinkVideo::Start(const char *filename, float xOrigin, float yOrigin, float width, float height)
|
||||
{
|
||||
assert(initialized);
|
||||
|
||||
// Check to see if a video is being played.
|
||||
if(status == NS_BV_PLAYING)
|
||||
{
|
||||
// stop
|
||||
this->Stop();
|
||||
}
|
||||
|
||||
// Hack! Remember if this was the logo movies, so that we can show the load screen later:
|
||||
if( strstr( filename, "logos" ) )
|
||||
loadScreenOnStop = true;
|
||||
else
|
||||
loadScreenOnStop = false;
|
||||
|
||||
// Blow away all sounds that aren't playing - this helps prevent crashing:
|
||||
SND_FreeOldestSound();
|
||||
|
||||
// Just use the zone for bink allocations:
|
||||
RADSetMemory( AllocWrapper, FreeWrapper );
|
||||
|
||||
// Set up sound for consoles
|
||||
|
||||
// We are on XBox, tell Bink to play all of the 5.1 tracks
|
||||
// U32 TrackIDsToPlay[ 4 ] = { 0, 1, 2, 3 };
|
||||
// BinkSetSoundTrack( 4, TrackIDsToPlay );
|
||||
|
||||
// Now route the sound tracks to the correct speaker
|
||||
// U32 bins[ 2 ];
|
||||
|
||||
// bins[ 0 ] = DSMIXBIN_FRONT_LEFT;
|
||||
// bins[ 1 ] = DSMIXBIN_FRONT_RIGHT;
|
||||
// BinkSetMixBins( bink, 0, bins, 2 );
|
||||
// bins[ 0 ] = DSMIXBIN_FRONT_CENTER;
|
||||
// BinkSetMixBins( bink, 1, bins, 1 );
|
||||
// bins[ 0 ] = DSMIXBIN_LOW_FREQUENCY;
|
||||
// BinkSetMixBins( bink, 2, bins, 1 );
|
||||
// bins[ 0 ] = DSMIXBIN_BACK_LEFT;
|
||||
// bins[ 1 ] = DSMIXBIN_BACK_RIGHT;
|
||||
// BinkSetMixBins( bink, 3, bins, 2 );
|
||||
|
||||
// Try to open the Bink file.
|
||||
// bink = BinkOpen( filename, BINKSNDTRACK | BINKALPHA );
|
||||
bink = BinkOpen( filename, BINKALPHA );
|
||||
if(!bink)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(bink->Width <= MAX_WIDTH && bink->Height <=MAX_HEIGHT);
|
||||
|
||||
// Did the source .bik file have an alpha plane?
|
||||
alpha = (bool)(bink->OpenFlags & BINKALPHA);
|
||||
|
||||
// set the height, width, etc...
|
||||
x1 = xOrigin;
|
||||
y1 = yOrigin;
|
||||
x2 = x1 + width;
|
||||
y2 = y1 + height;
|
||||
|
||||
// flush any background sound reads
|
||||
extern void S_DrainRawSoundData(void);
|
||||
S_DrainRawSoundData();
|
||||
|
||||
// Full-screen movies (without alpha) need a pair of YUV2 textures:
|
||||
if( !alpha )
|
||||
{
|
||||
// YUY2 is 16 bpp? But we need two:
|
||||
gTextures.SwapTextureMemory( (bink->Width * bink->Height * 4) + 1024 );
|
||||
|
||||
// Make our two textures:
|
||||
Image[0].texture = new IDirect3DTexture9;
|
||||
Image[1].texture = new IDirect3DTexture9;
|
||||
|
||||
// Fill in the texture headers:
|
||||
DWORD pixelSize =
|
||||
XGSetTextureHeader( bink->Width,
|
||||
bink->Height,
|
||||
1,
|
||||
0,
|
||||
D3DFMT_YUY2,
|
||||
0,
|
||||
Image[0].texture,
|
||||
0,
|
||||
0 );
|
||||
|
||||
XGSetTextureHeader( bink->Width,
|
||||
bink->Height,
|
||||
1,
|
||||
0,
|
||||
D3DFMT_YUY2,
|
||||
0,
|
||||
Image[1].texture,
|
||||
0,
|
||||
0 );
|
||||
|
||||
// texNum is unused:
|
||||
Image[0].texture->Register( gTextures.Allocate( pixelSize, 0 ) );
|
||||
Image[1].texture->Register( gTextures.Allocate( pixelSize, 0 ) );
|
||||
|
||||
// Turn on overlays:
|
||||
glw_state->device->EnableOverlay( TRUE );
|
||||
|
||||
// Get surface pointers:
|
||||
Image[0].texture->GetSurfaceLevel( 0, &Image[0].surface );
|
||||
Image[1].texture->GetSurfaceLevel( 0, &Image[1].surface );
|
||||
|
||||
// Just to be safe:
|
||||
currentImage = 0;
|
||||
buffer = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Planet movies (with alpha) re-use tr.binkPlanetImage, so no texture setup
|
||||
// is needed. But we do need a temporary buffer to decompress into. Let's steal
|
||||
// from the bone pool.
|
||||
buffer = BonePoolTempAlloc( bink->Width * bink->Height * 4 );
|
||||
}
|
||||
|
||||
status = NS_BV_PLAYING;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*********
|
||||
Run
|
||||
Decompresses a frame, renders it to the screen, and advances to
|
||||
the next frame. Only used for full-screen movies (no alpha).
|
||||
*********/
|
||||
bool BinkVideo::Run(void)
|
||||
{
|
||||
// Make sure movie is running:
|
||||
if( status == NS_BV_STOPPED )
|
||||
return false;
|
||||
|
||||
// Wait for proper frame timing:
|
||||
while(BinkWait(bink));
|
||||
|
||||
// Are we supposed to stop now?
|
||||
if( stopNextFrame )
|
||||
{
|
||||
stopNextFrame = false;
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to decompress the frame:
|
||||
if( DecompressFrame( &Image[currentImage ^ 1] ) == 0 )
|
||||
{
|
||||
// The blt succeeded, update our current image index.
|
||||
currentImage ^= 1;
|
||||
|
||||
// Draw the next frame.
|
||||
Draw( &Image[currentImage] );
|
||||
}
|
||||
|
||||
// Are we done? Set a flag, we don't want to stop until next frame, so the
|
||||
// last frame stays up for the right amount of time!
|
||||
if( bink->FrameNum == bink->Frames && !looping )
|
||||
{
|
||||
stopNextFrame = true;
|
||||
}
|
||||
|
||||
// Keep playing:
|
||||
BinkNextFrame( bink );
|
||||
|
||||
// Are we done?
|
||||
/*
|
||||
if( bink->FrameNum == (bink->Frames - 1) && !looping )
|
||||
{
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*********
|
||||
GetBinkData
|
||||
Returns the buffer data for the next frame of the video - only used for
|
||||
movies with alpha (the planets).
|
||||
|
||||
This doesn't follow Bink guidelines. They suggest that you call BinkWait()
|
||||
very frequently, something like 4 to 5 times as fast as the framerate of
|
||||
the movie. We're technically coming close to that, but this code won't work
|
||||
if we have videoMap shaders with higher framerates than the planets (8).
|
||||
*********/
|
||||
void* BinkVideo::GetBinkData(void)
|
||||
{
|
||||
assert( alpha );
|
||||
|
||||
if (!BinkWait(bink))
|
||||
{
|
||||
BinkDoFrame(bink);
|
||||
|
||||
BinkCopyToBuffer( bink,
|
||||
buffer,
|
||||
bink->Width * 4, // Pitch
|
||||
bink->Height,
|
||||
0,
|
||||
0,
|
||||
BINKCOPYALL | BINKSURFACE32A );
|
||||
|
||||
BinkNextFrame(bink);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/********
|
||||
Draw
|
||||
Draws the current movie full-screen
|
||||
********/
|
||||
void BinkVideo::Draw( OVERLAYINFO * oi )
|
||||
{
|
||||
// Draw the image on the screen (centered)...
|
||||
RECT dst_rect = { 0, 0, 640, 480 };
|
||||
RECT src_rect = { 0, 0, bink->Width, bink->Height };
|
||||
|
||||
// Update this bugger.
|
||||
glw_state->device->UpdateOverlay( oi->surface, &src_rect, &dst_rect, FALSE, 0 );
|
||||
}
|
||||
|
||||
/*********
|
||||
Stop
|
||||
Stops the current movie, and clears it from memory
|
||||
*********/
|
||||
void BinkVideo::Stop(void)
|
||||
{
|
||||
if( bink ) {
|
||||
BinkClose( bink );
|
||||
}
|
||||
|
||||
if( alpha )
|
||||
{
|
||||
// Release all the temp space we grabbed, no texture cleanup to do:
|
||||
if( buffer )
|
||||
BonePoolTempFree( buffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
// We wrap all this in a single check - it should be all or nothing:
|
||||
if( Image[0].surface )
|
||||
{
|
||||
// Release surfaces:
|
||||
Image[0].surface->Release();
|
||||
Image[0].surface = NULL;
|
||||
|
||||
Image[1].surface->Release();
|
||||
Image[1].surface = NULL;
|
||||
|
||||
// Clean up the textures we made for the overlay stuff:
|
||||
Image[0].texture->BlockUntilNotBusy();
|
||||
delete Image[0].texture;
|
||||
Image[0].texture = NULL;
|
||||
|
||||
Image[1].texture->BlockUntilNotBusy();
|
||||
delete Image[1].texture;
|
||||
Image[1].texture = NULL;
|
||||
|
||||
// We're going to be stripping the overlay off, leave a black screen,
|
||||
// unless it was the logo movies that we just played, in which case we
|
||||
// draw the loading screen!
|
||||
if( loadScreenOnStop )
|
||||
{
|
||||
SP_DrawSPLoadScreen();
|
||||
glw_state->device->BlockUntilVerticalBlank();
|
||||
|
||||
// Filth. Don't call Present until this gets cleared.
|
||||
extern bool connectSwapOverride;
|
||||
connectSwapOverride = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
glw_state->device->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_COLORVALUE(0, 0, 0, 0), 0, 0 );
|
||||
glw_state->device->Present( NULL, NULL, NULL, NULL );
|
||||
glw_state->device->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_COLORVALUE(0, 0, 0, 0), 0, 0 );
|
||||
glw_state->device->Present( NULL, NULL, NULL, NULL );
|
||||
glw_state->device->BlockUntilVerticalBlank();
|
||||
}
|
||||
|
||||
// Turn overlays back off:
|
||||
glw_state->device->EnableOverlay( FALSE );
|
||||
|
||||
// Restore the textures that we dumped to disk
|
||||
gTextures.UnswapTextureMemory();
|
||||
}
|
||||
}
|
||||
|
||||
x1 = 0.0f;
|
||||
y1 = 0.0f;
|
||||
x2 = 0.0f;
|
||||
y2 = 0.0f;
|
||||
buffer = NULL;
|
||||
bink = NULL;
|
||||
status = NS_BV_STOPPED;
|
||||
|
||||
// Now free all the temp memory that Bink took with it's internal allocations:
|
||||
TempFree();
|
||||
|
||||
if( !alpha && (cls.state == CA_CINEMATIC || cls.state == CA_ACTIVE) )
|
||||
re.InitDissolve(qfalse);
|
||||
}
|
||||
|
||||
/*********
|
||||
SetExtents
|
||||
Sets dimmension variables
|
||||
*********/
|
||||
|
||||
void BinkVideo::SetExtents(float xOrigin, float yOrigin, float width, float height)
|
||||
{
|
||||
x1 = xOrigin;
|
||||
y1 = yOrigin;
|
||||
x2 = x1 + width;
|
||||
y2 = y1 + height;
|
||||
}
|
||||
|
||||
/*********
|
||||
SetMasterVolume
|
||||
Sets the volume of the specified track
|
||||
*********/
|
||||
void BinkVideo::SetMasterVolume(s32 volume)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
BinkSetVolume(bink,i,volume);
|
||||
}
|
||||
}
|
||||
|
||||
/*********
|
||||
DecompressFrame
|
||||
Decompresses current frame and copies the data to
|
||||
the buffer
|
||||
*********/
|
||||
S32 BinkVideo::DecompressFrame( OVERLAYINFO *oi )
|
||||
{
|
||||
s32 copy_skipped;
|
||||
D3DLOCKED_RECT lock_rect;
|
||||
|
||||
// Decompress the Bink frame.
|
||||
BinkDoFrame( bink );
|
||||
|
||||
// Lock the 3D image so that we can copy the decompressed frame into it.
|
||||
oi->texture->LockRect( 0, &lock_rect, 0, 0 );
|
||||
|
||||
// Copy the decompressed frame into the 3D image.
|
||||
copy_skipped = BinkCopyToBuffer( bink,
|
||||
lock_rect.pBits,
|
||||
lock_rect.Pitch,
|
||||
bink->Height,
|
||||
0, 0,
|
||||
BINKSURFACEYUY2 | BINKCOPYALL );
|
||||
|
||||
// Unlock the 3D image.
|
||||
oi->texture->UnlockRect( 0 );
|
||||
|
||||
return copy_skipped;
|
||||
}
|
||||
|
||||
/*********
|
||||
Allocate
|
||||
Allocates memory for the frame buffer
|
||||
*********/
|
||||
void *BinkVideo::Allocate(U32 size)
|
||||
{
|
||||
void *retVal = TempAlloc( size );
|
||||
|
||||
// Fall back to Zone if we didn't get it
|
||||
if( !retVal )
|
||||
retVal = Z_Malloc(size, TAG_BINK, qfalse, 32);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/*********
|
||||
FreeBuffer
|
||||
Releases the frame buffer memory
|
||||
*********/
|
||||
void BinkVideo::Free(void* ptr)
|
||||
{
|
||||
// Did this pointer come from the Zone up above?
|
||||
if( !Z_IsFromTempPool( ptr ) )
|
||||
Z_Free(ptr);
|
||||
|
||||
// Else, do nothing - we don't free temp allocations until movie is done
|
||||
}
|
||||
72
code/client/BinkVideo.h
Normal file
72
code/client/BinkVideo.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef NS_BINKVIDEO
|
||||
#define NS_BINKVIDEO
|
||||
|
||||
#include "bink.h"
|
||||
#define NS_BV_DEFAULT_CIN_BPS (4)
|
||||
#define MAX_WIDTH 512
|
||||
#define MAX_HEIGHT 512
|
||||
|
||||
#define XBOX_BUFFER_SIZE NS_BV_DEFAULT_CIN_BPS * MAX_WIDTH * MAX_HEIGHT
|
||||
#define XBOX_BINK_SND_MEM 16448
|
||||
|
||||
typedef enum {
|
||||
NS_BV_PLAYING, // Movie is playing
|
||||
NS_BV_STOPPED, // Movie is stopped
|
||||
};
|
||||
|
||||
struct OVERLAYINFO
|
||||
{
|
||||
D3DTexture *texture;
|
||||
D3DSurface *surface;
|
||||
};
|
||||
|
||||
class BinkVideo
|
||||
{
|
||||
private:
|
||||
HBINK bink;
|
||||
void *buffer; // Only used for movies with alpha
|
||||
// int texture;
|
||||
int status;
|
||||
bool looping;
|
||||
bool alpha; // Important flag
|
||||
float x1;
|
||||
float y1;
|
||||
float x2;
|
||||
float y2;
|
||||
|
||||
bool loadScreenOnStop; // Set to true when we play the logos, so we know to show the loading screen
|
||||
|
||||
bool stopNextFrame; // Used to stop movies with *correct* timing
|
||||
|
||||
OVERLAYINFO Image[2];
|
||||
|
||||
unsigned currentImage;
|
||||
|
||||
bool initialized;
|
||||
|
||||
void Draw( OVERLAYINFO *oi );
|
||||
S32 DecompressFrame( OVERLAYINFO *oi );
|
||||
|
||||
public:
|
||||
|
||||
BinkVideo();
|
||||
~BinkVideo();
|
||||
bool Start(const char *filename, float xOrigin, float yOrigin, float width, float height);
|
||||
bool Run(void);
|
||||
void Stop(void);
|
||||
void SetExtents(float xOrigin, float yOrigin, float width, float height);
|
||||
int GetStatus(void) { return status; }
|
||||
void SetLooping(bool loop) { looping = loop; }
|
||||
void* GetBinkData(void);
|
||||
int GetBinkWidth(void) { return this->bink->Width; }
|
||||
int GetBinkHeight(void) { return this->bink->Height; }
|
||||
void SetMasterVolume(s32 volume);
|
||||
void AllocateXboxMem(void);
|
||||
void FreeXboxMem(void);
|
||||
static void* Allocate(U32 size);
|
||||
static void Free(void* ptr);
|
||||
|
||||
bool Ready(void) { return (bool)this->bink; }
|
||||
};
|
||||
|
||||
#endif
|
||||
564
code/client/OpenAL/al.h
Normal file
564
code/client/OpenAL/al.h
Normal file
@@ -0,0 +1,564 @@
|
||||
#ifndef _AL_H_
|
||||
#define _AL_H_
|
||||
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2000 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
#include "altypes.h"
|
||||
|
||||
#ifdef _XBOX
|
||||
#define ALAPI
|
||||
#define ALAPIENTRY
|
||||
#define AL_CALLBACK
|
||||
#else
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _OPENAL32LIB
|
||||
#define ALAPI __declspec(dllexport)
|
||||
#else
|
||||
#define ALAPI __declspec(dllimport)
|
||||
#endif
|
||||
#define ALAPIENTRY __cdecl
|
||||
#define AL_CALLBACK
|
||||
#else
|
||||
#ifdef TARGET_OS_MAC
|
||||
#if TARGET_OS_MAC
|
||||
#pragma export on
|
||||
#endif
|
||||
#endif
|
||||
#define ALAPI
|
||||
#define ALAPIENTRY __cdecl
|
||||
#define AL_CALLBACK
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define OPENAL
|
||||
|
||||
#ifndef AL_NO_PROTOTYPES
|
||||
|
||||
/**
|
||||
* OpenAL Maintenance Functions
|
||||
* Initialization and exiting.
|
||||
* State Management and Query.
|
||||
* Error Handling.
|
||||
* Extension Support.
|
||||
*/
|
||||
|
||||
/** State management. */
|
||||
ALAPI ALvoid ALAPIENTRY alEnable( ALenum capability );
|
||||
ALAPI ALvoid ALAPIENTRY alDisable( ALenum capability );
|
||||
ALAPI ALboolean ALAPIENTRY alIsEnabled( ALenum capability );
|
||||
|
||||
/** Application preferences for driver performance choices. */
|
||||
ALAPI ALvoid ALAPIENTRY alHint( ALenum target, ALenum mode );
|
||||
|
||||
/** State retrieval. */
|
||||
ALAPI ALboolean ALAPIENTRY alGetBoolean( ALenum param );
|
||||
ALAPI ALint ALAPIENTRY alGetInteger( ALenum param );
|
||||
ALAPI ALfloat ALAPIENTRY alGetFloat( ALenum param );
|
||||
ALAPI ALdouble ALAPIENTRY alGetDouble( ALenum param );
|
||||
ALAPI ALvoid ALAPIENTRY alGetBooleanv( ALenum param, ALboolean* data );
|
||||
ALAPI ALvoid ALAPIENTRY alGetIntegerv( ALenum param, ALint* data );
|
||||
ALAPI ALvoid ALAPIENTRY alGetFloatv( ALenum param, ALfloat* data );
|
||||
ALAPI ALvoid ALAPIENTRY alGetDoublev( ALenum param, ALdouble* data );
|
||||
ALAPI ALubyte* ALAPIENTRY alGetString( ALenum param );
|
||||
|
||||
/**
|
||||
* Error support.
|
||||
* Obtain the most recent error generated in the AL state machine.
|
||||
*/
|
||||
ALAPI ALenum ALAPIENTRY alGetError( ALvoid );
|
||||
|
||||
#ifdef _XBOX
|
||||
/**
|
||||
* Update cycle.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY alUpdate( ALvoid );
|
||||
|
||||
/**
|
||||
* Returns a global state parameter.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY alGeti( ALenum param, ALint* value );
|
||||
|
||||
/**
|
||||
* Adjust the size of the sound buffer pool.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY alResizePool( ALuint size );
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Extension support.
|
||||
* Obtain the address of a function (usually an extension)
|
||||
* with the name fname. All addresses are context-independent.
|
||||
*/
|
||||
ALAPI ALboolean ALAPIENTRY alIsExtensionPresent( ALubyte* fname );
|
||||
|
||||
|
||||
/**
|
||||
* Extension support.
|
||||
* Obtain the address of a function (usually an extension)
|
||||
* with the name fname. All addresses are context-independent.
|
||||
*/
|
||||
ALAPI ALvoid* ALAPIENTRY alGetProcAddress( ALubyte* fname );
|
||||
|
||||
|
||||
/**
|
||||
* Extension support.
|
||||
* Obtain the integer value of an enumeration (usually an extension) with the name ename.
|
||||
*/
|
||||
ALAPI ALenum ALAPIENTRY alGetEnumValue( ALubyte* ename );
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* LISTENER
|
||||
* Listener is the sample position for a given context.
|
||||
* The multi-channel (usually stereo) output stream generated
|
||||
* by the mixer is parametrized by this Listener object:
|
||||
* its position and velocity relative to Sources, within
|
||||
* occluder and reflector geometry.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef _XBOX
|
||||
/**
|
||||
* Listener create and delete
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY alGenListeners( ALsizei n, ALuint* listeners );
|
||||
ALAPI ALvoid ALAPIENTRY alDeleteListeners( ALsizei n, ALuint* listeners );
|
||||
#endif
|
||||
|
||||
// VV's Console version of openAL includes multiple listener support,
|
||||
// as an extra first arg to the alListener functions. We wrap that up
|
||||
// in a macro here, to make the following more concise.
|
||||
#ifdef _XBOX
|
||||
#define AL_VV_LISTENER ALuint listener,
|
||||
#else
|
||||
#define AL_VV_LISTENER
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* Listener Environment: default 0.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY alListeneri( AL_VV_LISTENER ALenum param, ALint value );
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Listener Gain: default 1.0f.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY alListenerf( AL_VV_LISTENER ALenum param, ALfloat value );
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Listener Position.
|
||||
* Listener Velocity.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY alListener3f( AL_VV_LISTENER ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 );
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Listener Position: ALfloat[3]
|
||||
* Listener Velocity: ALfloat[3]
|
||||
* Listener Orientation: ALfloat[6] (forward and up vector).
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY alListenerfv( AL_VV_LISTENER ALenum param, ALfloat* values );
|
||||
|
||||
ALAPI ALvoid ALAPIENTRY alGetListeneri( AL_VV_LISTENER ALenum param, ALint* value );
|
||||
ALAPI ALvoid ALAPIENTRY alGetListenerf( AL_VV_LISTENER ALenum param, ALfloat* value );
|
||||
ALAPI ALvoid ALAPIENTRY alGetListener3f( AL_VV_LISTENER ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 );
|
||||
ALAPI ALvoid ALAPIENTRY alGetListenerfv( AL_VV_LISTENER ALenum param, ALfloat* values );
|
||||
|
||||
|
||||
/**
|
||||
* SOURCE
|
||||
* Source objects are by default localized. Sources
|
||||
* take the PCM data provided in the specified Buffer,
|
||||
* apply Source-specific modifications, and then
|
||||
* submit them to be mixed according to spatial
|
||||
* arrangement etc.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** Create Source objects. */
|
||||
#ifdef _XBOX
|
||||
ALAPI ALvoid ALAPIENTRY alGenSources2D( ALsizei n, ALuint* sources );
|
||||
ALAPI ALvoid ALAPIENTRY alGenSources3D( ALsizei n, ALuint* sources );
|
||||
#else
|
||||
ALAPI ALvoid ALAPIENTRY alGenSources( ALsizei n, ALuint* sources );
|
||||
#endif
|
||||
|
||||
/** Delete Source objects. */
|
||||
ALAPI ALvoid ALAPIENTRY alDeleteSources( ALsizei n, ALuint* sources );
|
||||
|
||||
/** Verify a handle is a valid Source. */
|
||||
ALAPI ALboolean ALAPIENTRY alIsSource( ALuint id );
|
||||
|
||||
/** Set an integer parameter for a Source object. */
|
||||
ALAPI ALvoid ALAPIENTRY alSourcei( ALuint source, ALenum param, ALint value );
|
||||
ALAPI ALvoid ALAPIENTRY alSourcef( ALuint source, ALenum param, ALfloat value );
|
||||
ALAPI ALvoid ALAPIENTRY alSource3f( ALuint source, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 );
|
||||
ALAPI ALvoid ALAPIENTRY alSourcefv( ALuint source, ALenum param, ALfloat* values );
|
||||
|
||||
/** Get an integer parameter for a Source object. */
|
||||
ALAPI ALvoid ALAPIENTRY alGetSourcei( ALuint source, ALenum param, ALint* value );
|
||||
ALAPI ALvoid ALAPIENTRY alGetSourcef( ALuint source, ALenum param, ALfloat* value );
|
||||
ALAPI ALvoid ALAPIENTRY alGetSource3f( ALuint source, ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 );
|
||||
ALAPI ALvoid ALAPIENTRY alGetSourcefv( ALuint source, ALenum param, ALfloat* values );
|
||||
|
||||
ALAPI ALvoid ALAPIENTRY alSourcePlayv( ALsizei n, ALuint *sources );
|
||||
ALAPI ALvoid ALAPIENTRY alSourcePausev( ALsizei n, ALuint *sources );
|
||||
ALAPI ALvoid ALAPIENTRY alSourceStopv( ALsizei n, ALuint *sources );
|
||||
ALAPI ALvoid ALAPIENTRY alSourceRewindv(ALsizei n,ALuint *sources);
|
||||
|
||||
/** Activate a source, start replay. */
|
||||
ALAPI ALvoid ALAPIENTRY alSourcePlay( ALuint source );
|
||||
|
||||
/**
|
||||
* Pause a source,
|
||||
* temporarily remove it from the mixer list.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY alSourcePause( ALuint source );
|
||||
|
||||
/**
|
||||
* Stop a source,
|
||||
* temporarily remove it from the mixer list,
|
||||
* and reset its internal state to pre-Play.
|
||||
* To remove a Source completely, it has to be
|
||||
* deleted following Stop, or before Play.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY alSourceStop( ALuint source );
|
||||
|
||||
/**
|
||||
* Rewinds a source,
|
||||
* temporarily remove it from the mixer list,
|
||||
* and reset its internal state to pre-Play.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY alSourceRewind( ALuint source );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* BUFFER
|
||||
* Buffer objects are storage space for sample data.
|
||||
* Buffers are referred to by Sources. There can be more than
|
||||
* one Source using the same Buffer data. If Buffers have
|
||||
* to be duplicated on a per-Source basis, the driver has to
|
||||
* take care of allocation, copying, and deallocation as well
|
||||
* as propagating buffer data changes.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/** Buffer object generation. */
|
||||
ALAPI ALvoid ALAPIENTRY alGenBuffers( ALsizei n, ALuint* buffers );
|
||||
ALAPI ALvoid ALAPIENTRY alDeleteBuffers( ALsizei n, ALuint* buffers );
|
||||
ALAPI ALboolean ALAPIENTRY alIsBuffer( ALuint buffer );
|
||||
|
||||
/**
|
||||
* Specify the data to be filled into a buffer.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY alBufferData( ALuint buffer,
|
||||
ALenum format,
|
||||
ALvoid* data,
|
||||
ALsizei size,
|
||||
ALsizei freq );
|
||||
|
||||
|
||||
ALAPI ALvoid ALAPIENTRY alGetBufferi( ALuint buffer, ALenum param, ALint* value );
|
||||
ALAPI ALvoid ALAPIENTRY alGetBufferf( ALuint buffer, ALenum param, ALfloat* value );
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Queue stuff
|
||||
*/
|
||||
|
||||
ALAPI ALvoid ALAPIENTRY alSourceQueueBuffers( ALuint source, ALsizei n, ALuint* buffers );
|
||||
ALAPI ALvoid ALAPIENTRY alSourceUnqueueBuffers( ALuint source, ALsizei n, ALuint* buffers );
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef _XBOX
|
||||
/**
|
||||
* STREAM
|
||||
* Stream objects encapsulate traditional sound stream and
|
||||
* act as both sources and buffers. They emit sound and
|
||||
* manage sound data.
|
||||
*/
|
||||
|
||||
ALAPI ALvoid ALAPIENTRY alGenStream( ALvoid );
|
||||
ALAPI ALvoid ALAPIENTRY alDeleteStream( ALvoid );
|
||||
|
||||
ALAPI ALvoid ALAPIENTRY alStreamStop( ALvoid );
|
||||
ALAPI ALvoid ALAPIENTRY alStreamPlay( ALsizei offset, ALint file, ALint loop );
|
||||
|
||||
ALAPI ALvoid ALAPIENTRY alStreamf( ALenum param, ALfloat value );
|
||||
|
||||
ALAPI ALvoid ALAPIENTRY alGetStreamf( ALenum param, ALfloat* value );
|
||||
ALAPI ALvoid ALAPIENTRY alGetStreami( ALenum param, ALint* value );
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Knobs and dials
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY alDistanceModel( ALenum value );
|
||||
ALAPI ALvoid ALAPIENTRY alDopplerFactor( ALfloat value );
|
||||
ALAPI ALvoid ALAPIENTRY alDopplerVelocity( ALfloat value );
|
||||
#ifdef _XBOX
|
||||
ALAPI ALvoid ALAPIENTRY alGain( ALfloat value );
|
||||
#endif
|
||||
|
||||
#else /* AL_NO_PROTOTYPES */
|
||||
|
||||
/**
|
||||
* OpenAL Maintenance Functions
|
||||
* Initialization and exiting.
|
||||
* State Management and Query.
|
||||
* Error Handling.
|
||||
* Extension Support.
|
||||
*/
|
||||
|
||||
/** State management. */
|
||||
ALAPI ALvoid ALAPIENTRY (*alEnable)( ALenum capability );
|
||||
ALAPI ALvoid ALAPIENTRY (*alDisable)( ALenum capability );
|
||||
ALAPI ALboolean ALAPIENTRY (*alIsEnabled)( ALenum capability );
|
||||
|
||||
/** Application preferences for driver performance choices. */
|
||||
ALAPI ALvoid ALAPIENTRY (*alHint)( ALenum target, ALenum mode );
|
||||
|
||||
/** State retrieval. */
|
||||
ALAPI ALboolean ALAPIENTRY (*alGetBoolean)( ALenum param );
|
||||
ALAPI ALint ALAPIENTRY (*alGetInteger)( ALenum param );
|
||||
ALAPI ALfloat ALAPIENTRY (*alGetFloat)( ALenum param );
|
||||
ALAPI ALdouble ALAPIENTRY (*alGetDouble)( ALenum param );
|
||||
ALAPI ALvoid ALAPIENTRY (*alGetBooleanv)( ALenum param, ALboolean* data );
|
||||
ALAPI ALvoid ALAPIENTRY (*alGetIntegerv)( ALenum param, ALint* data );
|
||||
ALAPI ALvoid ALAPIENTRY (*alGetFloatv)( ALenum param, ALfloat* data );
|
||||
ALAPI ALvoid ALAPIENTRY (*alGetDoublev)( ALenum param, ALdouble* data );
|
||||
ALAPI ALubyte* ALAPIENTRY (*alGetString)( ALenum param );
|
||||
|
||||
/**
|
||||
* Error support.
|
||||
* Obtain the most recent error generated in the AL state machine.
|
||||
*/
|
||||
ALAPI ALenum ALAPIENTRY (*alGetError)( ALvoid );
|
||||
|
||||
|
||||
/**
|
||||
* Extension support.
|
||||
* Obtain the address of a function (usually an extension)
|
||||
* with the name fname. All addresses are context-independent.
|
||||
*/
|
||||
ALAPI ALboolean ALAPIENTRY (*alIsExtensionPresent)( ALubyte* fname );
|
||||
|
||||
|
||||
/**
|
||||
* Extension support.
|
||||
* Obtain the address of a function (usually an extension)
|
||||
* with the name fname. All addresses are context-independent.
|
||||
*/
|
||||
ALAPI ALvoid* ALAPIENTRY (*alGetProcAddress)( ALubyte* fname );
|
||||
|
||||
|
||||
/**
|
||||
* Extension support.
|
||||
* Obtain the integer value of an enumeration (usually an extension) with the name ename.
|
||||
*/
|
||||
ALAPI ALenum ALAPIENTRY (*alGetEnumValue)( ALubyte* ename );
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* LISTENER
|
||||
* Listener is the sample position for a given context.
|
||||
* The multi-channel (usually stereo) output stream generated
|
||||
* by the mixer is parametrized by this Listener object:
|
||||
* its position and velocity relative to Sources, within
|
||||
* occluder and reflector geometry.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Listener Environment: default 0.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY (*alListeneri)( ALenum param, ALint value );
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Listener Gain: default 1.0f.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY (*alListenerf)( ALenum param, ALfloat value );
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Listener Position.
|
||||
* Listener Velocity.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY (*alListener3f)( ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 );
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Listener Position: ALfloat[3]
|
||||
* Listener Velocity: ALfloat[3]
|
||||
* Listener Orientation: ALfloat[6] (forward and up vector).
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY (*alListenerfv)( ALenum param, ALfloat* values );
|
||||
|
||||
ALAPI ALvoid ALAPIENTRY (*alGetListeneri)( ALenum param, ALint* value );
|
||||
ALAPI ALvoid ALAPIENTRY (*alGetListenerf)( ALenum param, ALfloat* value );
|
||||
ALAPI ALvoid ALAPIENTRY (*alGetListener3f)( ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 );
|
||||
ALAPI ALvoid ALAPIENTRY (*alGetListenerfv)( ALenum param, ALfloat* values );
|
||||
|
||||
|
||||
/**
|
||||
* SOURCE
|
||||
* Source objects are by default localized. Sources
|
||||
* take the PCM data provided in the specified Buffer,
|
||||
* apply Source-specific modifications, and then
|
||||
* submit them to be mixed according to spatial
|
||||
* arrangement etc.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/** Create Source objects. */
|
||||
ALAPI ALvoid ALAPIENTRY (*alGenSources)( ALsizei n, ALuint* sources );
|
||||
|
||||
/** Delete Source objects. */
|
||||
ALAPI ALvoid ALAPIENTRY (*alDeleteSources)( ALsizei n, ALuint* sources );
|
||||
|
||||
/** Verify a handle is a valid Source. */
|
||||
ALAPI ALboolean ALAPIENTRY (*alIsSource)( ALuint id );
|
||||
|
||||
/** Set an integer parameter for a Source object. */
|
||||
ALAPI ALvoid ALAPIENTRY (*alSourcei)( ALuint source, ALenum param, ALint value );
|
||||
ALAPI ALvoid ALAPIENTRY (*alSourcef)( ALuint source, ALenum param, ALfloat value );
|
||||
ALAPI ALvoid ALAPIENTRY (*alSource3f)( ALuint source, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 );
|
||||
ALAPI ALvoid ALAPIENTRY (*alSourcefv)( ALuint source, ALenum param, ALfloat* values );
|
||||
|
||||
/** Get an integer parameter for a Source object. */
|
||||
ALAPI ALvoid ALAPIENTRY (*alGetSourcei)( ALuint source, ALenum param, ALint* value );
|
||||
ALAPI ALvoid ALAPIENTRY (*alGetSourcef)( ALuint source, ALenum param, ALfloat* value );
|
||||
ALAPI ALvoid ALAPIENTRY (*alGetSourcefv)( ALuint source, ALenum param, ALfloat* values );
|
||||
|
||||
ALAPI ALvoid ALAPIENTRY (*alSourcePlayv)( ALsizei n, ALuint *sources );
|
||||
ALAPI ALvoid ALAPIENTRY (*alSourceStopv)( ALsizei n, ALuint *sources );
|
||||
|
||||
/** Activate a source, start replay. */
|
||||
ALAPI ALvoid ALAPIENTRY (*alSourcePlay)( ALuint source );
|
||||
|
||||
/**
|
||||
* Pause a source,
|
||||
* temporarily remove it from the mixer list.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY (*alSourcePause)( ALuint source );
|
||||
|
||||
/**
|
||||
* Stop a source,
|
||||
* temporarily remove it from the mixer list,
|
||||
* and reset its internal state to pre-Play.
|
||||
* To remove a Source completely, it has to be
|
||||
* deleted following Stop, or before Play.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY (*alSourceStop)( ALuint source );
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* BUFFER
|
||||
* Buffer objects are storage space for sample data.
|
||||
* Buffers are referred to by Sources. There can be more than
|
||||
* one Source using the same Buffer data. If Buffers have
|
||||
* to be duplicated on a per-Source basis, the driver has to
|
||||
* take care of allocation, copying, and deallocation as well
|
||||
* as propagating buffer data changes.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/** Buffer object generation. */
|
||||
ALAPI ALvoid ALAPIENTRY (*alGenBuffers)( ALsizei n, ALuint* buffers );
|
||||
ALAPI ALvoid ALAPIENTRY (*alDeleteBuffers)( ALsizei n, ALuint* buffers );
|
||||
ALAPI ALboolean ALAPIENTRY (*alIsBuffer)( ALuint buffer );
|
||||
|
||||
/**
|
||||
* Specify the data to be filled into a buffer.
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY (*alBufferData)( ALuint buffer,
|
||||
ALenum format,
|
||||
ALvoid* data,
|
||||
ALsizei size,
|
||||
ALsizei freq );
|
||||
|
||||
ALAPI ALvoid ALAPIENTRY (*alGetBufferi)( ALuint buffer, ALenum param, ALint* value );
|
||||
ALAPI ALvoid ALAPIENTRY (*alGetBufferf)( ALuint buffer, ALenum param, ALfloat* value );
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Queue stuff
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY (*alSourceQueueBuffers)( ALuint source, ALsizei n, ALuint* buffers );
|
||||
ALAPI ALvoid ALAPIENTRY (*alSourceUnqueueBuffers)( ALuint source, ALsizei n, ALuint* buffers );
|
||||
|
||||
/**
|
||||
* Knobs and dials
|
||||
*/
|
||||
ALAPI ALvoid ALAPIENTRY (*alDistanceModel)( ALenum value );
|
||||
ALAPI ALvoid ALAPIENTRY (*alDopplerFactor)( ALfloat value );
|
||||
ALAPI ALvoid ALAPIENTRY (*alDopplerVelocity)( ALfloat value );
|
||||
|
||||
#endif /* AL_NO_PROTOTYPES */
|
||||
|
||||
#ifdef TARGET_OS_MAC
|
||||
#if TARGET_OS_MAC
|
||||
#pragma export off
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _XBOX
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
97
code/client/OpenAL/alc.h
Normal file
97
code/client/OpenAL/alc.h
Normal file
@@ -0,0 +1,97 @@
|
||||
#ifndef _ALC_H_
|
||||
#define _ALC_H_
|
||||
|
||||
#include "altypes.h"
|
||||
#include "alctypes.h"
|
||||
|
||||
#ifdef _XBOX
|
||||
#define ALCAPI
|
||||
#define ALCAPIENTRY
|
||||
#else
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _OPENAL32LIB
|
||||
#define ALCAPI __declspec(dllexport)
|
||||
#else
|
||||
#define ALCAPI __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
typedef struct ALCdevice_struct ALCdevice;
|
||||
typedef struct ALCcontext_struct ALCcontext;
|
||||
|
||||
#define ALCAPIENTRY __cdecl
|
||||
#else
|
||||
#ifdef TARGET_OS_MAC
|
||||
#if TARGET_OS_MAC
|
||||
#pragma export on
|
||||
#endif
|
||||
#endif
|
||||
#define ALCAPI
|
||||
#define ALCAPIENTRY __cdecl
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef ALC_NO_PROTOTYPES
|
||||
|
||||
ALCAPI ALCubyte* ALCAPIENTRY alcGetString(ALCdevice *device,ALCenum param);
|
||||
ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALCsizei size,ALCint *data);
|
||||
|
||||
ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(ALCubyte *deviceName);
|
||||
ALCAPI ALCvoid ALCAPIENTRY alcCloseDevice(ALCdevice *device);
|
||||
|
||||
ALCAPI ALCcontext*ALCAPIENTRY alcCreateContext(ALCdevice *device,ALCint *attrList);
|
||||
ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context);
|
||||
ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *context);
|
||||
ALCAPI ALCcontext*ALCAPIENTRY alcGetCurrentContext(ALCvoid);
|
||||
ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *context);
|
||||
ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *context);
|
||||
ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context);
|
||||
|
||||
ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device);
|
||||
|
||||
ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device,ALCubyte *extName);
|
||||
ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device,ALCubyte *funcName);
|
||||
ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device,ALCubyte *enumName);
|
||||
|
||||
#else /* AL_NO_PROTOTYPES */
|
||||
|
||||
ALCAPI ALCubyte* ALCAPIENTRY (*alcGetString)(ALCdevice *device,ALCenum param);
|
||||
ALCAPI ALCvoid ALCAPIENTRY (*alcGetIntegerv)(ALCdevice * device,ALCenum param,ALCsizei size,ALCint *data);
|
||||
|
||||
ALCAPI ALCdevice* ALCAPIENTRY (*alcOpenDevice)(ALubyte *deviceName);
|
||||
ALCAPI ALCvoid ALCAPIENTRY (*alcCloseDevice)(ALCdevice *device);
|
||||
|
||||
ALCAPI ALCcontext*ALCAPIENTRY (*alcCreateContext)(ALCdevice *device,ALCint *attrList);
|
||||
ALCAPI ALCboolean ALCAPIENTRY (*alcMakeContextCurrent)(ALCcontext *context);
|
||||
ALCAPI ALCvoid ALCAPIENTRY (*alcProcessContext)(ALCcontext *context);
|
||||
ALCAPI ALCcontext*ALCAPIENTRY (*alcGetCurrentContext)(ALCvoid);
|
||||
ALCAPI ALCdevice* ALCAPIENTRY (*alcGetContextsDevice)(ALCcontext *context);
|
||||
ALCAPI ALCvoid ALCAPIENTRY (*alcSuspendContext)(ALCcontext *context);
|
||||
ALCAPI ALCvoid ALCAPIENTRY (*alcDestroyContext)(ALCcontext *context);
|
||||
|
||||
ALCAPI ALCenum ALCAPIENTRY (*alcGetError)(ALCdevice *device);
|
||||
|
||||
ALCAPI ALCboolean ALCAPIENTRY (*alcIsExtensionPresent)(ALCdevice *device,ALCubyte *extName);
|
||||
ALCAPI ALCvoid * ALCAPIENTRY (*alcGetProcAddress)(ALCdevice *device,ALCubyte *funcName);
|
||||
ALCAPI ALCenum ALCAPIENTRY (*alcGetEnumValue)(ALCdevice *device,ALCubyte *enumName);
|
||||
|
||||
#endif /* AL_NO_PROTOTYPES */
|
||||
|
||||
#ifdef TARGET_OS_MAC
|
||||
#if TARGET_OS_MAC
|
||||
#pragma export off
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _XBOX
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
133
code/client/OpenAL/alctypes.h
Normal file
133
code/client/OpenAL/alctypes.h
Normal file
@@ -0,0 +1,133 @@
|
||||
#ifndef _ALCTYPES_H_
|
||||
#define _ALCTYPES_H_
|
||||
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2000 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef _XBOX
|
||||
/** ALC device type. */
|
||||
typedef int ALCdevice;
|
||||
|
||||
/** ALC context type. */
|
||||
typedef int ALCcontext;
|
||||
#endif
|
||||
|
||||
/** ALC boolean type. */
|
||||
typedef char ALCboolean;
|
||||
|
||||
/** ALC 8bit signed byte. */
|
||||
typedef char ALCbyte;
|
||||
|
||||
/** ALC 8bit unsigned byte. */
|
||||
typedef unsigned char ALCubyte;
|
||||
|
||||
/** ALC 16bit signed short integer type. */
|
||||
typedef short ALCshort;
|
||||
|
||||
/** ALC 16bit unsigned short integer type. */
|
||||
typedef unsigned short ALCushort;
|
||||
|
||||
/** ALC 32bit unsigned integer type. */
|
||||
typedef unsigned ALCuint;
|
||||
|
||||
/** ALC 32bit signed integer type. */
|
||||
typedef int ALCint;
|
||||
|
||||
/** ALC 32bit floating point type. */
|
||||
typedef float ALCfloat;
|
||||
|
||||
/** ALC 64bit double point type. */
|
||||
typedef double ALCdouble;
|
||||
|
||||
/** ALC 32bit type. */
|
||||
typedef unsigned int ALCsizei;
|
||||
|
||||
/** ALC void type */
|
||||
typedef void ALCvoid;
|
||||
|
||||
/** ALC enumerations. */
|
||||
typedef int ALCenum;
|
||||
|
||||
/* Bad value. */
|
||||
#define ALC_INVALID (-1)
|
||||
|
||||
/* Boolean False. */
|
||||
#define ALC_FALSE 0
|
||||
|
||||
/* Boolean True. */
|
||||
#define ALC_TRUE 1
|
||||
|
||||
/** Errors: No Error. */
|
||||
#define ALC_NO_ERROR ALC_FALSE
|
||||
|
||||
#define ALC_MAJOR_VERSION 0x1000
|
||||
#define ALC_MINOR_VERSION 0x1001
|
||||
#define ALC_ATTRIBUTES_SIZE 0x1002
|
||||
#define ALC_ALL_ATTRIBUTES 0x1003
|
||||
|
||||
#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004
|
||||
#define ALC_DEVICE_SPECIFIER 0x1005
|
||||
#define ALC_EXTENSIONS 0x1006
|
||||
|
||||
#define ALC_FREQUENCY 0x1007
|
||||
#define ALC_REFRESH 0x1008
|
||||
#define ALC_SYNC 0x1009
|
||||
|
||||
/**
|
||||
* The device argument does not name a valid dvice.
|
||||
*/
|
||||
#define ALC_INVALID_DEVICE 0xA001
|
||||
|
||||
/**
|
||||
* The context argument does not name a valid context.
|
||||
*/
|
||||
#define ALC_INVALID_CONTEXT 0xA002
|
||||
|
||||
/**
|
||||
* A function was called at inappropriate time,
|
||||
* or in an inappropriate way, causing an illegal state.
|
||||
* This can be an incompatible ALenum, object ID,
|
||||
* and/or function.
|
||||
*/
|
||||
#define ALC_INVALID_ENUM 0xA003
|
||||
|
||||
/**
|
||||
* Illegal value passed as an argument to an AL call.
|
||||
* Applies to parameter values, but not to enumerations.
|
||||
*/
|
||||
#define ALC_INVALID_VALUE 0xA004
|
||||
|
||||
/**
|
||||
* A function could not be completed,
|
||||
* because there is not enough memory available.
|
||||
*/
|
||||
#define ALC_OUT_OF_MEMORY 0xA005
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
351
code/client/OpenAL/altypes.h
Normal file
351
code/client/OpenAL/altypes.h
Normal file
@@ -0,0 +1,351 @@
|
||||
#ifndef _ALTYPES_H_
|
||||
#define _ALTYPES_H_
|
||||
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2000 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** OpenAL boolean type. */
|
||||
typedef char ALboolean;
|
||||
|
||||
/** OpenAL 8bit signed byte. */
|
||||
typedef char ALbyte;
|
||||
|
||||
/** OpenAL 8bit unsigned byte. */
|
||||
typedef unsigned char ALubyte;
|
||||
|
||||
/** OpenAL 16bit signed short integer type. */
|
||||
typedef short ALshort;
|
||||
|
||||
/** OpenAL 16bit unsigned short integer type. */
|
||||
typedef unsigned short ALushort;
|
||||
|
||||
/** OpenAL 32bit unsigned integer type. */
|
||||
typedef unsigned ALuint;
|
||||
|
||||
/** OpenAL 32bit signed integer type. */
|
||||
typedef int ALint;
|
||||
|
||||
/** OpenAL 32bit floating point type. */
|
||||
typedef float ALfloat;
|
||||
|
||||
/** OpenAL 64bit double point type. */
|
||||
typedef double ALdouble;
|
||||
|
||||
/** OpenAL 32bit type. */
|
||||
typedef unsigned int ALsizei;
|
||||
|
||||
/** OpenAL void type */
|
||||
typedef void ALvoid;
|
||||
|
||||
/** OpenAL enumerations. */
|
||||
typedef int ALenum;
|
||||
|
||||
/* Bad value. */
|
||||
#define AL_INVALID (-1)
|
||||
|
||||
/* Disable value. */
|
||||
#define AL_NONE 0
|
||||
|
||||
/* Boolean False. */
|
||||
#define AL_FALSE 0
|
||||
|
||||
/* Boolean True. */
|
||||
#define AL_TRUE 1
|
||||
|
||||
/**
|
||||
* Indicate the type of AL_SOURCE.
|
||||
* Sources can be spatialized
|
||||
*/
|
||||
#define AL_SOURCE_TYPE 0x200
|
||||
|
||||
/** Indicate source has absolute coordinates. */
|
||||
#define AL_SOURCE_ABSOLUTE 0x201
|
||||
|
||||
/** Indicate Source has listener relative coordinates. */
|
||||
#define AL_SOURCE_RELATIVE 0x202
|
||||
|
||||
/**
|
||||
* Directional source, inner cone angle, in degrees.
|
||||
* Range: [0-360]
|
||||
* Default: 360
|
||||
*/
|
||||
#define AL_CONE_INNER_ANGLE 0x1001
|
||||
|
||||
/**
|
||||
* Directional source, outer cone angle, in degrees.
|
||||
* Range: [0-360]
|
||||
* Default: 360
|
||||
*/
|
||||
#define AL_CONE_OUTER_ANGLE 0x1002
|
||||
|
||||
/**
|
||||
* Specify the pitch to be applied, either at source,
|
||||
* or on mixer results, at listener.
|
||||
* Range: [0.5-2.0]
|
||||
* Default: 1.0
|
||||
*/
|
||||
#define AL_PITCH 0x1003
|
||||
|
||||
/**
|
||||
* Specify the current location in three dimensional space.
|
||||
* OpenAL, like OpenGL, uses a right handed coordinate system,
|
||||
* where in a frontal default view X (thumb) points right,
|
||||
* Y points up (index finger), and Z points towards the
|
||||
* viewer/camera (middle finger).
|
||||
* To switch from a left handed coordinate system, flip the
|
||||
* sign on the Z coordinate.
|
||||
* Listener position is always in the world coordinate system.
|
||||
*/
|
||||
#define AL_POSITION 0x1004
|
||||
|
||||
/** Specify the current direction as forward vector. */
|
||||
#define AL_DIRECTION 0x1005
|
||||
|
||||
/** Specify the current velocity in three dimensional space. */
|
||||
#define AL_VELOCITY 0x1006
|
||||
|
||||
/**
|
||||
* Indicate whether source has to loop infinite.
|
||||
* Type: ALboolean
|
||||
* Range: [AL_TRUE, AL_FALSE]
|
||||
* Default: AL_FALSE
|
||||
*/
|
||||
#define AL_LOOPING 0x1007
|
||||
|
||||
/**
|
||||
* Indicate the buffer to provide sound samples.
|
||||
* Type: ALuint.
|
||||
* Range: any valid Buffer id.
|
||||
*/
|
||||
#define AL_BUFFER 0x1009
|
||||
|
||||
/**
|
||||
* Indicate the gain (volume amplification) applied.
|
||||
* Type: ALfloat.
|
||||
* Range: ]0.0- ]
|
||||
* A value of 1.0 means un-attenuated/unchanged.
|
||||
* Each division by 2 equals an attenuation of -6dB.
|
||||
* Each multiplicaton with 2 equals an amplification of +6dB.
|
||||
* A value of 0.0 is meaningless with respect to a logarithmic
|
||||
* scale; it is interpreted as zero volume - the channel
|
||||
* is effectively disabled.
|
||||
*/
|
||||
#define AL_GAIN 0x100A
|
||||
|
||||
/**
|
||||
* Indicate minimum source attenuation.
|
||||
* Type: ALfloat
|
||||
* Range: [0.0 - 1.0]
|
||||
*/
|
||||
#define AL_MIN_GAIN 0x100D
|
||||
|
||||
/**
|
||||
* Indicate maximum source attenuation.
|
||||
* Type: ALfloat
|
||||
* Range: [0.0 - 1.0]
|
||||
*/
|
||||
#define AL_MAX_GAIN 0x100E
|
||||
|
||||
/**
|
||||
* Specify the current orientation.
|
||||
* Type: ALfv6 (at/up)
|
||||
* Range: N/A
|
||||
*/
|
||||
#define AL_ORIENTATION 0x100F
|
||||
|
||||
/* byte offset into source (in canon format). -1 if source
|
||||
* is not playing. Don't set this, get this.
|
||||
*
|
||||
* Type: ALfloat
|
||||
* Range: [0.0 - ]
|
||||
* Default: 1.0
|
||||
*/
|
||||
#define AL_REFERENCE_DISTANCE 0x1020
|
||||
|
||||
/**
|
||||
* Indicate the rolloff factor for the source.
|
||||
* Type: ALfloat
|
||||
* Range: [0.0 - ]
|
||||
* Default: 1.0
|
||||
*/
|
||||
#define AL_ROLLOFF_FACTOR 0x1021
|
||||
|
||||
/**
|
||||
* Indicate the gain (volume amplification) applied.
|
||||
* Type: ALfloat.
|
||||
* Range: ]0.0- ]
|
||||
* A value of 1.0 means un-attenuated/unchanged.
|
||||
* Each division by 2 equals an attenuation of -6dB.
|
||||
* Each multiplicaton with 2 equals an amplification of +6dB.
|
||||
* A value of 0.0 is meaningless with respect to a logarithmic
|
||||
* scale; it is interpreted as zero volume - the channel
|
||||
* is effectively disabled.
|
||||
*/
|
||||
#define AL_CONE_OUTER_GAIN 0x1022
|
||||
|
||||
/**
|
||||
* Specify the maximum distance.
|
||||
* Type: ALfloat
|
||||
* Range: [0.0 - ]
|
||||
*/
|
||||
#define AL_MAX_DISTANCE 0x1023
|
||||
|
||||
/**
|
||||
* Specify the panning to be applied (2D only.)
|
||||
* Range: [-1.0 - 1.0]
|
||||
* Default: 0.0
|
||||
*/
|
||||
#define AL_PAN 0x1024
|
||||
|
||||
/**
|
||||
* Get the playing time of a stream.
|
||||
* Range: [0.0 - infinity]
|
||||
*/
|
||||
#define AL_TIME 0x1025
|
||||
|
||||
/**
|
||||
* Specify the channel mask. (Creative)
|
||||
* Type: ALuint
|
||||
* Range: [0 - 255]
|
||||
*/
|
||||
#define AL_CHANNEL_MASK 0x3000
|
||||
|
||||
/**
|
||||
* Source state information
|
||||
*/
|
||||
#define AL_SOURCE_STATE 0x1010
|
||||
#define AL_INITIAL 0x1011
|
||||
#define AL_PLAYING 0x1012
|
||||
#define AL_PAUSED 0x1013
|
||||
#define AL_STOPPED 0x1014
|
||||
|
||||
/**
|
||||
* Buffer Queue params
|
||||
*/
|
||||
#define AL_BUFFERS_QUEUED 0x1015
|
||||
#define AL_BUFFERS_PROCESSED 0x1016
|
||||
|
||||
/** Sound buffers: format specifier. */
|
||||
#define AL_FORMAT_MONO8 0x1100
|
||||
#define AL_FORMAT_MONO16 0x1101
|
||||
#define AL_FORMAT_STEREO8 0x1102
|
||||
#define AL_FORMAT_STEREO16 0x1103
|
||||
#define AL_FORMAT_MONO4 0x1104
|
||||
#define AL_FORMAT_STEREO4 0x1105
|
||||
|
||||
/**
|
||||
* Sound buffers: frequency, in units of Hertz [Hz].
|
||||
* This is the number of samples per second. Half of the
|
||||
* sample frequency marks the maximum significant
|
||||
* frequency component.
|
||||
*/
|
||||
#define AL_FREQUENCY 0x2001
|
||||
#define AL_BITS 0x2002
|
||||
#define AL_CHANNELS 0x2003
|
||||
#define AL_SIZE 0x2004
|
||||
#define AL_DATA 0x2005
|
||||
|
||||
/**
|
||||
* Buffer state.
|
||||
*
|
||||
* Not supported for public use (yet).
|
||||
*/
|
||||
#define AL_UNUSED 0x2010
|
||||
#define AL_PENDING 0x2011
|
||||
#define AL_PROCESSED 0x2012
|
||||
|
||||
/** Errors: No Error. */
|
||||
#define AL_NO_ERROR AL_FALSE
|
||||
|
||||
/**
|
||||
* Illegal name passed as an argument to an AL call.
|
||||
*/
|
||||
#define AL_INVALID_NAME 0xA001
|
||||
|
||||
/**
|
||||
* Illegal enum passed as an argument to an AL call.
|
||||
*/
|
||||
#define AL_INVALID_ENUM 0xA002
|
||||
/**
|
||||
* Illegal value passed as an argument to an AL call.
|
||||
* Applies to parameter values, but not to enumerations.
|
||||
*/
|
||||
#define AL_INVALID_VALUE 0xA003
|
||||
|
||||
/**
|
||||
* A function was called at inappropriate time,
|
||||
* or in an inappropriate way, causing an illegal state.
|
||||
* This can be an incompatible ALenum, object ID,
|
||||
* and/or function.
|
||||
*/
|
||||
#define AL_INVALID_OPERATION 0xA004
|
||||
|
||||
/**
|
||||
* A function could not be completed,
|
||||
* because there is not enough memory available.
|
||||
*/
|
||||
#define AL_OUT_OF_MEMORY 0xA005
|
||||
|
||||
/** Context strings: Vendor Name. */
|
||||
#define AL_VENDOR 0xB001
|
||||
#define AL_VERSION 0xB002
|
||||
#define AL_RENDERER 0xB003
|
||||
#define AL_EXTENSIONS 0xB004
|
||||
#define AL_MEMORY_USED 0xB005
|
||||
#define AL_MEMORY_ALLOCATOR 0xB006
|
||||
#define AL_MEMORY_DEALLOCATOR 0xB007
|
||||
#define AL_STEREO 0xB008
|
||||
|
||||
/** Global tweakage. */
|
||||
|
||||
/**
|
||||
* Doppler scale. Default 1.0
|
||||
*/
|
||||
#define AL_DOPPLER_FACTOR 0xC000
|
||||
|
||||
/**
|
||||
* Doppler velocity. Default 1.0
|
||||
*/
|
||||
#define AL_DOPPLER_VELOCITY 0xC001
|
||||
|
||||
/**
|
||||
* Distance model. Default AL_INVERSE_DISTANCE_CLAMPED
|
||||
*/
|
||||
#define AL_DISTANCE_MODEL 0xD000
|
||||
|
||||
/** Distance models. */
|
||||
|
||||
#define AL_INVERSE_DISTANCE 0xD001
|
||||
#define AL_INVERSE_DISTANCE_CLAMPED 0xD002
|
||||
|
||||
/**
|
||||
* enables
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
34
code/client/OpenAL/alu.h
Normal file
34
code/client/OpenAL/alu.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef _ALU_H_
|
||||
#define _ALU_H_
|
||||
|
||||
#define ALUAPI
|
||||
#define ALUAPIENTRY __cdecl
|
||||
|
||||
#define BUFFERSIZE 48000
|
||||
#define FRACTIONBITS 14
|
||||
#define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
|
||||
#define OUTPUTCHANNELS 2
|
||||
|
||||
#include "altypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
ALUAPI ALint ALUAPIENTRY aluF2L(ALfloat value);
|
||||
ALUAPI ALshort ALUAPIENTRY aluF2S(ALfloat value);
|
||||
ALUAPI ALvoid ALUAPIENTRY aluCrossproduct(ALfloat *inVector1,ALfloat *inVector2,ALfloat *outVector);
|
||||
ALUAPI ALfloat ALUAPIENTRY aluDotproduct(ALfloat *inVector1,ALfloat *inVector2);
|
||||
ALUAPI ALvoid ALUAPIENTRY aluNormalize(ALfloat *inVector);
|
||||
ALUAPI ALvoid ALUAPIENTRY aluMatrixVector(ALfloat matrix[3][3],ALfloat *vector);
|
||||
ALUAPI ALvoid ALUAPIENTRY aluCalculateSourceParameters(ALuint source,ALuint channels,ALfloat *drysend,ALfloat *wetsend,ALfloat *pitch);
|
||||
ALUAPI ALvoid ALUAPIENTRY aluMixData(ALvoid *context,ALvoid *buffer,ALsizei size,ALenum format);
|
||||
ALUAPI ALvoid ALUAPIENTRY aluSetReverb(ALvoid *Reverb,ALuint Environment);
|
||||
ALUAPI ALvoid ALUAPIENTRY aluReverb(ALvoid *Reverb,ALfloat Buffer[][2],ALsizei BufferSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
24
code/client/OpenAL/alut.h
Normal file
24
code/client/OpenAL/alut.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef _ALUT_H_
|
||||
#define _ALUT_H_
|
||||
|
||||
#define ALUTAPI
|
||||
#define ALUTAPIENTRY __cdecl
|
||||
|
||||
#include "al.h"
|
||||
#include "alu.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
ALUTAPI ALvoid ALUTAPIENTRY alutInit(ALint *argc,ALbyte **argv);
|
||||
ALUTAPI ALvoid ALUTAPIENTRY alutExit(ALvoid);
|
||||
ALUTAPI ALvoid ALUTAPIENTRY alutLoadWAVFile(ALbyte *file,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq,ALboolean *loop);
|
||||
ALUTAPI ALvoid ALUTAPIENTRY alutLoadWAVMemory(ALbyte *memory,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq,ALboolean *loop);
|
||||
ALUTAPI ALvoid ALUTAPIENTRY alutUnloadWAV(ALenum format,ALvoid *data,ALsizei size,ALsizei freq);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
66
code/client/cl_bink_copier.cpp
Normal file
66
code/client/cl_bink_copier.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
|
||||
/*
|
||||
* UNPUBLISHED -- Rights reserved under the copyright laws of the
|
||||
* United States. Use of a copyright notice is precautionary only and
|
||||
* does not imply publication or disclosure.
|
||||
*
|
||||
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
|
||||
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
|
||||
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
|
||||
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
|
||||
*/
|
||||
|
||||
#include <xtl.h>
|
||||
|
||||
HANDLE s_BCThread = INVALID_HANDLE_VALUE;
|
||||
|
||||
static DWORD WINAPI _BinkCopier(LPVOID)
|
||||
{
|
||||
#ifndef FINAL_BUILD
|
||||
OutputDebugString( "_BinkCopier starting.\n" );
|
||||
#endif
|
||||
|
||||
#ifdef XBOX_DEMO
|
||||
// Demo only has two planets, and needs to re-map paths.
|
||||
// But we're in a thread, and va isn't thread-safe. Fuck.
|
||||
char planetPath[64];
|
||||
extern char demoBasePath[64];
|
||||
|
||||
strcpy( planetPath, demoBasePath );
|
||||
strcat( planetPath, "\\base\\video\\tatooine.bik" );
|
||||
CopyFile( planetPath, "Z:\\tatooine.bik", FALSE );
|
||||
|
||||
strcpy( planetPath, demoBasePath );
|
||||
strcat( planetPath, "\\base\\video\\chandrila.bik" );
|
||||
CopyFile( planetPath, "Z:\\chandrila.bik", FALSE );
|
||||
#else
|
||||
CopyFile( "D:\\base\\video\\cos.bik", "Z:\\cos.bik", FALSE );
|
||||
CopyFile( "D:\\base\\video\\bakura.bik", "Z:\\bakura.bik", FALSE );
|
||||
CopyFile( "D:\\base\\video\\blenjeel.bik", "Z:\\blenjeel.bik", FALSE );
|
||||
CopyFile( "D:\\base\\video\\chandrila.bik", "Z:\\chandrila.bik", FALSE );
|
||||
CopyFile( "D:\\base\\video\\core.bik", "Z:\\core.bik", FALSE );
|
||||
CopyFile( "D:\\base\\video\\ast.bik", "Z:\\ast.bik", FALSE );
|
||||
CopyFile( "D:\\base\\video\\dosunn.bik", "Z:\\dosunn.bik", FALSE );
|
||||
CopyFile( "D:\\base\\video\\krildor.bik", "Z:\\krildor.bik", FALSE );
|
||||
CopyFile( "D:\\base\\video\\narkreeta.bik", "Z:\\narkreeta.bik", FALSE );
|
||||
CopyFile( "D:\\base\\video\\ordman.bik", "Z:\\ordman.bik", FALSE );
|
||||
CopyFile( "D:\\base\\video\\tanaab.bik", "Z:\\tanaab.bik", FALSE );
|
||||
CopyFile( "D:\\base\\video\\tatooine.bik", "Z:\\tatooine.bik", FALSE );
|
||||
CopyFile( "D:\\base\\video\\yalara.bik", "Z:\\yalara.bik", FALSE );
|
||||
CopyFile( "D:\\base\\video\\zonju.bik", "Z:\\zonju.bik", FALSE );
|
||||
#endif
|
||||
|
||||
#ifndef FINAL_BUILD
|
||||
OutputDebugString( "_BinkCopier exiting.\n" );
|
||||
#endif
|
||||
|
||||
ExitThread(0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Spawn our short-lived worker thread that copies all the planet movies to the Z: drive
|
||||
void Sys_BinkCopyInit(void)
|
||||
{
|
||||
// Create a thread to service IO
|
||||
s_BCThread = CreateThread(NULL, 64*1024, _BinkCopier, 0, 0, NULL);
|
||||
}
|
||||
1384
code/client/cl_cgame.cpp
Normal file
1384
code/client/cl_cgame.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1955
code/client/cl_cin.cpp
Normal file
1955
code/client/cl_cin.cpp
Normal file
File diff suppressed because it is too large
Load Diff
478
code/client/cl_cin_console.cpp
Normal file
478
code/client/cl_cin_console.cpp
Normal file
@@ -0,0 +1,478 @@
|
||||
|
||||
/*****************************************************************************
|
||||
* name: cl_cin_console.cpp
|
||||
*
|
||||
* desc: video and cinematic playback interface for Xbox (using Bink)
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "client.h"
|
||||
#include "../win32/win_local.h"
|
||||
#include "../win32/win_input.h"
|
||||
#include "../win32/glw_win_dx8.h"
|
||||
#include "BinkVideo.h"
|
||||
|
||||
//#define XBOX_VIDEO_PATH "d:\\base\\video\\"
|
||||
char XBOX_VIDEO_PATH[64] = "d:\\base\\video\\";
|
||||
#define SHADER_VIDEO_PATH "z:\\"
|
||||
|
||||
BinkVideo bVideo; // bink video object
|
||||
connstate_t previousState = CA_UNINITIALIZED; // previous cinematic state
|
||||
|
||||
struct CinematicData
|
||||
{
|
||||
char filename[MAX_OSPATH]; // No path, no extension
|
||||
int x, y, w, h; // Dimensions
|
||||
int bits; // Flags (loop, silent, shader)
|
||||
};
|
||||
|
||||
// We have a fixed lookup table of all cinematics that can be played
|
||||
// Video handles are just indices into the array. An entry is not
|
||||
// considered initialized until its width is nonzero
|
||||
CinematicData cinFiles[] = {
|
||||
// Opening logos
|
||||
{ "logos", 0, 0, 0, 0, 0 },
|
||||
// Attract sequence
|
||||
{ "attract", 0, 0, 0, 0, 0 },
|
||||
|
||||
// Planet shaders
|
||||
{ "cos", 0, 0, 0, 0, 0 },
|
||||
{ "bakura", 0, 0, 0, 0, 0 },
|
||||
{ "blenjeel", 0, 0, 0, 0, 0 },
|
||||
{ "chandrila", 0, 0, 0, 0, 0 },
|
||||
{ "core", 0, 0, 0, 0, 0 },
|
||||
{ "ast", 0, 0, 0, 0, 0 },
|
||||
{ "dosunn", 0, 0, 0, 0, 0 },
|
||||
{ "krildor", 0, 0, 0, 0, 0 },
|
||||
{ "narkreeta", 0, 0, 0, 0, 0 },
|
||||
{ "ordman", 0, 0, 0, 0, 0 },
|
||||
{ "tanaab", 0, 0, 0, 0, 0 },
|
||||
{ "tatooine", 0, 0, 0, 0, 0 },
|
||||
{ "yalara", 0, 0, 0, 0, 0 },
|
||||
{ "zonju", 0, 0, 0, 0, 0 },
|
||||
|
||||
// Others
|
||||
// { "jk0101_sw", 0, 0, 0, 0, 0 }, // Folded into ja01!
|
||||
// { "ja01", 0, 0, 0, 0, 0 }, // Contains the text crawl, so must be localized:
|
||||
{ "ja01_e", 0, 0, 0, 0, 0 },
|
||||
{ "ja01_f", 0, 0, 0, 0, 0 },
|
||||
{ "ja01_d", 0, 0, 0, 0, 0 },
|
||||
{ "ja02", 0, 0, 0, 0, 0 },
|
||||
{ "ja03", 0, 0, 0, 0, 0 },
|
||||
{ "ja04", 0, 0, 0, 0, 0 },
|
||||
{ "ja05", 0, 0, 0, 0, 0 },
|
||||
{ "ja06", 0, 0, 0, 0, 0 },
|
||||
{ "ja07", 0, 0, 0, 0, 0 },
|
||||
{ "ja08", 0, 0, 0, 0, 0 },
|
||||
{ "ja09", 0, 0, 0, 0, 0 },
|
||||
{ "ja10", 0, 0, 0, 0, 0 },
|
||||
{ "ja11", 0, 0, 0, 0, 0 },
|
||||
{ "ja12", 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
const int cinNumFiles = sizeof(cinFiles) / sizeof(cinFiles[0]);
|
||||
static int currentHandle = -1;
|
||||
|
||||
// Stupid PC filth
|
||||
static qboolean qbInGameCinematicOnStandBy = qfalse;
|
||||
static char sInGameCinematicStandingBy[MAX_QPATH];
|
||||
|
||||
bool CIN_PlayAllFrames( const char *arg, int x, int y, int w, int h, int systemBits, bool keyBreakAllowed );
|
||||
|
||||
/********
|
||||
CIN_CloseAllVideos
|
||||
Stops all currently running videos
|
||||
*********/
|
||||
void CIN_CloseAllVideos(void)
|
||||
{
|
||||
// Stop the current bink video
|
||||
bVideo.Stop();
|
||||
currentHandle = -1;
|
||||
}
|
||||
|
||||
/********
|
||||
CIN_StopCinematic
|
||||
|
||||
handle - Not used
|
||||
return - FMV status
|
||||
|
||||
Stops the current cinematic
|
||||
*********/
|
||||
e_status CIN_StopCinematic(int handle)
|
||||
{
|
||||
assert( handle == currentHandle );
|
||||
currentHandle = -1;
|
||||
|
||||
if(previousState != CA_UNINITIALIZED)
|
||||
{
|
||||
cls.state = previousState;
|
||||
previousState = CA_UNINITIALIZED;
|
||||
}
|
||||
if(bVideo.GetStatus() != NS_BV_STOPPED)
|
||||
{
|
||||
bVideo.Stop();
|
||||
}
|
||||
return FMV_EOF;
|
||||
}
|
||||
|
||||
/********
|
||||
CIN_RunCinematic
|
||||
|
||||
handle - Ensure that the supplied cinematic is the one running
|
||||
return - FMV status
|
||||
|
||||
Fetch and decompress the pending frame
|
||||
*********/
|
||||
e_status CIN_RunCinematic (int handle)
|
||||
{
|
||||
if (handle < 0 || handle >= cinNumFiles || !cinFiles[handle].w)
|
||||
{
|
||||
assert( 0 );
|
||||
return FMV_EOF;
|
||||
}
|
||||
|
||||
// If we weren't playing a movie, or playing the wrong one - start up
|
||||
if (handle != currentHandle)
|
||||
{
|
||||
bool shader = cinFiles[handle].bits & CIN_shader;
|
||||
|
||||
CIN_StopCinematic(currentHandle);
|
||||
if (!bVideo.Start(
|
||||
va("%s%s.bik",
|
||||
shader ? SHADER_VIDEO_PATH : XBOX_VIDEO_PATH,
|
||||
cinFiles[handle].filename),
|
||||
cinFiles[handle].x, cinFiles[handle].y,
|
||||
cinFiles[handle].w, cinFiles[handle].h))
|
||||
{
|
||||
return FMV_EOF;
|
||||
}
|
||||
|
||||
if (cinFiles[handle].bits & CIN_loop)
|
||||
{
|
||||
bVideo.SetLooping(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
bVideo.SetLooping(false);
|
||||
}
|
||||
|
||||
if (cinFiles[handle].bits & CIN_silent)
|
||||
{
|
||||
bVideo.SetMasterVolume(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bVideo.SetMasterVolume(16384); //32768); // Default Bink volume
|
||||
}
|
||||
|
||||
if (!shader)
|
||||
{
|
||||
previousState = cls.state;
|
||||
cls.state = CA_CINEMATIC;
|
||||
}
|
||||
|
||||
currentHandle = handle;
|
||||
}
|
||||
|
||||
// Normal case does nothing here
|
||||
if(bVideo.GetStatus() == NS_BV_STOPPED)
|
||||
{
|
||||
return FMV_EOF;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FMV_PLAY;
|
||||
}
|
||||
}
|
||||
|
||||
/********
|
||||
CIN_PlayCinematic
|
||||
|
||||
arg0 - filename of bink video
|
||||
xpos - x origin
|
||||
ypos - y origin
|
||||
width - width of the movie window
|
||||
height - height of the movie window
|
||||
bits - CIN flags
|
||||
psAudioFile - audio file for movie (not used)
|
||||
|
||||
Starts playing the given bink video file
|
||||
*********/
|
||||
int CIN_PlayCinematic( const char *arg0, int xpos, int ypos, int width, int height, int bits, const char *psAudioFile /* = NULL */)
|
||||
{
|
||||
char arg[MAX_OSPATH];
|
||||
char* nameonly;
|
||||
int handle;
|
||||
|
||||
// get a local copy of the name
|
||||
strcpy(arg,arg0);
|
||||
|
||||
// remove path, find in list
|
||||
nameonly = COM_SkipPath(arg);
|
||||
|
||||
// ja01 contains the text crawl, so we need to add on the right language suffix
|
||||
extern DWORD g_dwLanguage;
|
||||
if( Q_stricmp(nameonly, "ja01") == 0)
|
||||
{
|
||||
switch( g_dwLanguage )
|
||||
{
|
||||
case XC_LANGUAGE_FRENCH:
|
||||
strcat(nameonly, "_f");
|
||||
break;
|
||||
case XC_LANGUAGE_GERMAN:
|
||||
strcat(nameonly, "_d");
|
||||
break;
|
||||
case XC_LANGUAGE_ENGLISH:
|
||||
default:
|
||||
strcat(nameonly, "_e");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (handle = 0; handle < cinNumFiles; ++handle)
|
||||
{
|
||||
if (!Q_stricmp(cinFiles[handle].filename, nameonly))
|
||||
break;
|
||||
}
|
||||
|
||||
// Don't have the requested movie in our table?
|
||||
if (handle == cinNumFiles)
|
||||
{
|
||||
Com_Printf( "ERROR: Movie file %s not found!\n", nameonly );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Store off information about the movie in the right place. Don't
|
||||
// actually play them movie, CIN_RunCinematic takes care of that.
|
||||
cinFiles[handle].x = xpos;
|
||||
cinFiles[handle].y = ypos;
|
||||
cinFiles[handle].w = width;
|
||||
cinFiles[handle].h = height;
|
||||
cinFiles[handle].bits = bits;
|
||||
currentHandle = -1;
|
||||
return handle;
|
||||
}
|
||||
|
||||
/*********
|
||||
CIN_SetExtents
|
||||
|
||||
handle - handle to a video
|
||||
x - x origin for window
|
||||
y - y origin for window
|
||||
w - width for window
|
||||
h - height for window
|
||||
*********/
|
||||
void CIN_SetExtents (int handle, int x, int y, int w, int h)
|
||||
{
|
||||
if (handle < 0 || handle >= cinNumFiles)
|
||||
return;
|
||||
|
||||
cinFiles[handle].x = x;
|
||||
cinFiles[handle].y = y;
|
||||
cinFiles[handle].w = w;
|
||||
cinFiles[handle].h = h;
|
||||
|
||||
if (handle == currentHandle)
|
||||
bVideo.SetExtents(x,y,w,h);
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
SCR_DrawCinematic
|
||||
|
||||
Externally-called only, and only if cls.state == CA_CINEMATIC (or CL_IsRunningInGameCinematic() == true now)
|
||||
*********/
|
||||
void SCR_DrawCinematic (void)
|
||||
{
|
||||
if (CL_InGameCinematicOnStandBy())
|
||||
{
|
||||
CIN_PlayAllFrames( sInGameCinematicStandingBy, 0, 0, 640, 480, 0, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Run and draw a frame:
|
||||
bVideo.Run();
|
||||
}
|
||||
}
|
||||
|
||||
/*********
|
||||
SCR_RunCinematic
|
||||
*********/
|
||||
void SCR_RunCinematic (void)
|
||||
{
|
||||
// This is called every frame, even when we're not playing a movie
|
||||
// VVFIXME - Check return val for EOF - then stop cinematic?
|
||||
if (currentHandle > 0 && currentHandle < cinNumFiles)
|
||||
CIN_RunCinematic(currentHandle);
|
||||
}
|
||||
|
||||
/*********
|
||||
SCR_StopCinematic
|
||||
*********/
|
||||
void SCR_StopCinematic(qboolean bAllowRefusal /* = qfalse */)
|
||||
{
|
||||
CIN_StopCinematic(currentHandle);
|
||||
}
|
||||
|
||||
/*********
|
||||
CIN_UploadCinematic
|
||||
|
||||
handle - (not used)
|
||||
|
||||
This function can be used to render a frame of a movie, if
|
||||
it needs to be done outside of CA_CINEMATIC. For example,
|
||||
a menu background or wall texture.
|
||||
*********/
|
||||
void CIN_UploadCinematic(int handle)
|
||||
{
|
||||
int w, h;
|
||||
byte* data;
|
||||
|
||||
assert( handle == currentHandle );
|
||||
|
||||
if(!bVideo.Ready()) {
|
||||
return;
|
||||
}
|
||||
|
||||
w = bVideo.GetBinkWidth();
|
||||
h = bVideo.GetBinkHeight();
|
||||
data = (byte*)bVideo.GetBinkData();
|
||||
|
||||
// handle is actually being used to pick from scratchImages in
|
||||
// this function - we only have two on Xbox, let's just use one.
|
||||
//re.UploadCinematic( w, h, data, handle, 1);
|
||||
re.UploadCinematic( w, h, data, 0, 1);
|
||||
}
|
||||
|
||||
/*********
|
||||
CIN_PlayAllFrames
|
||||
|
||||
arg - bink video filename
|
||||
x - x origin for movie
|
||||
y - y origin for movie
|
||||
w - width of the movie
|
||||
h - height of the movie
|
||||
systemBits - bit rate for movie
|
||||
keyBreakAllowed - if true, button press will end playback
|
||||
|
||||
Plays the target movie in full
|
||||
*********/
|
||||
bool CIN_PlayAllFrames( const char *arg, int x, int y, int w, int h, int systemBits, bool keyBreakAllowed )
|
||||
{
|
||||
bool retval;
|
||||
Key_ClearStates();
|
||||
|
||||
// PC hack
|
||||
qbInGameCinematicOnStandBy = qfalse;
|
||||
|
||||
#ifdef XBOX_DEMO
|
||||
// When run from CDX, we can pause the timer during cutscenes:
|
||||
extern void Demo_TimerPause( bool bPaused );
|
||||
Demo_TimerPause( true );
|
||||
#endif
|
||||
|
||||
int Handle = CIN_PlayCinematic(arg, x, y, w, h, systemBits, NULL);
|
||||
if (Handle != -1)
|
||||
{
|
||||
while (CIN_RunCinematic(Handle) == FMV_PLAY && !(keyBreakAllowed && kg.anykeydown))
|
||||
{
|
||||
SCR_UpdateScreen ();
|
||||
IN_Frame ();
|
||||
Com_EventLoop ();
|
||||
}
|
||||
#ifdef _XBOX
|
||||
// while (CIN_RunCinematic(Handle) == FMV_PLAY && !(keyBreakAllowed && !kg.anykeydown))
|
||||
// {
|
||||
// SCR_UpdateScreen ();
|
||||
// IN_Frame ();
|
||||
// Com_EventLoop ();
|
||||
// }
|
||||
#endif
|
||||
CIN_StopCinematic(Handle);
|
||||
}
|
||||
|
||||
#ifdef XBOX_DEMO
|
||||
Demo_TimerPause( false );
|
||||
#endif
|
||||
|
||||
retval =(keyBreakAllowed && kg.anykeydown);
|
||||
Key_ClearStates();
|
||||
|
||||
// Soooper hack! Game ends up running for a couple frames after this cutscene. We don't want it to!
|
||||
if( Q_stricmp(arg, "ja08") == 0 )
|
||||
{
|
||||
// Filth. Don't call Present until this gets cleared.
|
||||
extern bool connectSwapOverride;
|
||||
connectSwapOverride = true;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*********
|
||||
CIN_Init
|
||||
Initializes cinematic system
|
||||
*********/
|
||||
void CIN_Init(void)
|
||||
{
|
||||
// Allocate Memory for Bink System
|
||||
bVideo.AllocateXboxMem();
|
||||
}
|
||||
|
||||
/********
|
||||
CIN_Shutdown
|
||||
Shutdown the cinematic system
|
||||
********/
|
||||
void CIN_Shutdown(void)
|
||||
{
|
||||
// Free Memory for the Bink System
|
||||
bVideo.FreeXboxMem();
|
||||
}
|
||||
|
||||
|
||||
/***** Possible FIXME *****/
|
||||
/***** The following function may need to be implemented *****/
|
||||
/***** BEGIN *****/
|
||||
void CL_PlayCinematic_f(void)
|
||||
{
|
||||
char *arg;
|
||||
|
||||
arg = Cmd_Argv(1);
|
||||
CIN_PlayAllFrames(arg, 48, 36, 544, 408, 0, true);
|
||||
}
|
||||
|
||||
qboolean CL_IsRunningInGameCinematic(void)
|
||||
{
|
||||
return qfalse; //qbPlayingInGameCinematic;
|
||||
}
|
||||
|
||||
void CL_PlayInGameCinematic_f(void)
|
||||
{
|
||||
if (cls.state == CA_ACTIVE)
|
||||
{
|
||||
// In some situations (during yavin1 intro) we move to a cutscene directly from
|
||||
// a shaking camera - so rumble never gets killed.
|
||||
IN_KillRumbleScripts();
|
||||
|
||||
char *arg = Cmd_Argv( 1 );
|
||||
CIN_PlayAllFrames(arg, 48, 36, 544, 408, 0, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
qbInGameCinematicOnStandBy = qtrue;
|
||||
strcpy(sInGameCinematicStandingBy,Cmd_Argv(1));
|
||||
}
|
||||
}
|
||||
|
||||
qboolean CL_InGameCinematicOnStandBy(void)
|
||||
{
|
||||
return qbInGameCinematicOnStandBy;
|
||||
}
|
||||
|
||||
// Used by fatal error handler
|
||||
void MuteBinkSystem( void )
|
||||
{
|
||||
bVideo.SetMasterVolume( 0 );
|
||||
}
|
||||
/***** END *****/
|
||||
|
||||
730
code/client/cl_console.cpp
Normal file
730
code/client/cl_console.cpp
Normal file
@@ -0,0 +1,730 @@
|
||||
// console.c
|
||||
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
#include "client.h"
|
||||
#include "../qcommon/stv_version.h"
|
||||
|
||||
int g_console_field_width = 78;
|
||||
|
||||
console_t con;
|
||||
|
||||
cvar_t *con_conspeed;
|
||||
cvar_t *con_notifytime;
|
||||
cvar_t *con_conAlpha; //background alpha multiplier
|
||||
|
||||
#define DEFAULT_CONSOLE_WIDTH 78
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Con_ToggleConsole_f
|
||||
================
|
||||
*/
|
||||
void Con_ToggleConsole_f (void) {
|
||||
// closing a full screen console restarts the demo loop
|
||||
if ( cls.state == CA_DISCONNECTED && cls.keyCatchers == KEYCATCH_CONSOLE ) {
|
||||
// CL_StartDemoLoop();
|
||||
return;
|
||||
}
|
||||
|
||||
Field_Clear( &kg.g_consoleField );
|
||||
kg.g_consoleField.widthInChars = g_console_field_width;
|
||||
|
||||
Con_ClearNotify ();
|
||||
|
||||
cls.keyCatchers ^= KEYCATCH_CONSOLE;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Con_MessageMode_f
|
||||
================
|
||||
*/
|
||||
void Con_MessageMode_f (void) {
|
||||
Field_Clear( &chatField );
|
||||
chatField.widthInChars = 30;
|
||||
|
||||
// cls.keyCatchers ^= KEYCATCH_MESSAGE;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Con_Clear_f
|
||||
================
|
||||
*/
|
||||
void Con_Clear_f (void) {
|
||||
int i;
|
||||
|
||||
for ( i = 0 ; i < CON_TEXTSIZE ; i++ ) {
|
||||
con.text[i] = (ColorIndex(COLOR_WHITE)<<8) | ' ';
|
||||
}
|
||||
|
||||
Con_Bottom(); // go to end
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Con_Dump_f
|
||||
|
||||
Save the console contents out to a file
|
||||
================
|
||||
*/
|
||||
void Con_Dump_f (void)
|
||||
{
|
||||
#ifndef _XBOX
|
||||
int l, x, i;
|
||||
short *line;
|
||||
fileHandle_t f;
|
||||
char buffer[1024];
|
||||
|
||||
if (Cmd_Argc() != 2)
|
||||
{
|
||||
Com_Printf (SE_GetString("CON_TEXT_DUMP_USAGE"));
|
||||
return;
|
||||
}
|
||||
|
||||
Com_Printf ("Dumped console text to %s.\n", Cmd_Argv(1) );
|
||||
|
||||
f = FS_FOpenFileWrite( Cmd_Argv( 1 ) );
|
||||
if (!f)
|
||||
{
|
||||
Com_Printf (S_COLOR_RED"ERROR: couldn't open dump file.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// skip empty lines
|
||||
for (l = con.current - con.totallines + 1 ; l <= con.current ; l++)
|
||||
{
|
||||
line = con.text + (l%con.totallines)*con.linewidth;
|
||||
for (x=0 ; x<con.linewidth ; x++)
|
||||
if ((line[x] & 0xff) != ' ')
|
||||
break;
|
||||
if (x != con.linewidth)
|
||||
break;
|
||||
}
|
||||
|
||||
// write the remaining lines
|
||||
buffer[con.linewidth] = 0;
|
||||
for ( ; l <= con.current ; l++)
|
||||
{
|
||||
line = con.text + (l%con.totallines)*con.linewidth;
|
||||
for(i=0; i<con.linewidth; i++)
|
||||
buffer[i] = line[i] & 0xff;
|
||||
for (x=con.linewidth-1 ; x>=0 ; x--)
|
||||
{
|
||||
if (buffer[x] == ' ')
|
||||
buffer[x] = 0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
FS_Printf (f, "%s\n", buffer);
|
||||
}
|
||||
|
||||
FS_FCloseFile( f );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Con_ClearNotify
|
||||
================
|
||||
*/
|
||||
void Con_ClearNotify( void ) {
|
||||
int i;
|
||||
|
||||
for ( i = 0 ; i < NUM_CON_TIMES ; i++ ) {
|
||||
con.times[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Con_CheckResize
|
||||
|
||||
If the line width has changed, reformat the buffer.
|
||||
================
|
||||
*/
|
||||
void Con_CheckResize (void)
|
||||
{
|
||||
int i, j, width, oldwidth, oldtotallines, numlines, numchars;
|
||||
MAC_STATIC short tbuf[CON_TEXTSIZE];
|
||||
|
||||
//width = (SCREEN_WIDTH / SMALLCHAR_WIDTH) - 2;
|
||||
width = (cls.glconfig.vidWidth / SMALLCHAR_WIDTH) - 2;
|
||||
|
||||
if (width == con.linewidth)
|
||||
return;
|
||||
|
||||
if (width < 1) // video hasn't been initialized yet
|
||||
{
|
||||
con.xadjust = 1;
|
||||
con.yadjust = 1;
|
||||
width = DEFAULT_CONSOLE_WIDTH;
|
||||
con.linewidth = width;
|
||||
con.totallines = CON_TEXTSIZE / con.linewidth;
|
||||
for(i=0; i<CON_TEXTSIZE; i++)
|
||||
{
|
||||
con.text[i] = (ColorIndex(COLOR_WHITE)<<8) | ' ';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// on wide screens, we will center the text
|
||||
con.xadjust = 640.0f / cls.glconfig.vidWidth;
|
||||
con.yadjust = 480.0f / cls.glconfig.vidHeight;
|
||||
|
||||
oldwidth = con.linewidth;
|
||||
con.linewidth = width;
|
||||
oldtotallines = con.totallines;
|
||||
con.totallines = CON_TEXTSIZE / con.linewidth;
|
||||
numlines = oldtotallines;
|
||||
|
||||
if (con.totallines < numlines)
|
||||
numlines = con.totallines;
|
||||
|
||||
numchars = oldwidth;
|
||||
|
||||
if (con.linewidth < numchars)
|
||||
numchars = con.linewidth;
|
||||
|
||||
memcpy (tbuf, con.text, CON_TEXTSIZE * sizeof(short));
|
||||
for(i=0; i<CON_TEXTSIZE; i++)
|
||||
|
||||
con.text[i] = (ColorIndex(COLOR_WHITE)<<8) | ' ';
|
||||
|
||||
|
||||
for (i=0 ; i<numlines ; i++)
|
||||
{
|
||||
for (j=0 ; j<numchars ; j++)
|
||||
{
|
||||
con.text[(con.totallines - 1 - i) * con.linewidth + j] =
|
||||
tbuf[((con.current - i + oldtotallines) %
|
||||
oldtotallines) * oldwidth + j];
|
||||
}
|
||||
}
|
||||
|
||||
Con_ClearNotify ();
|
||||
}
|
||||
|
||||
con.current = con.totallines - 1;
|
||||
con.display = con.current;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Con_Init
|
||||
================
|
||||
*/
|
||||
void Con_Init (void) {
|
||||
int i;
|
||||
|
||||
con_notifytime = Cvar_Get ("con_notifytime", "3", 0);
|
||||
con_conspeed = Cvar_Get ("scr_conspeed", "3", 0);
|
||||
con_conAlpha= Cvar_Get( "conAlpha", "1.6", CVAR_ARCHIVE );
|
||||
|
||||
Field_Clear( &kg.g_consoleField );
|
||||
kg.g_consoleField.widthInChars = g_console_field_width;
|
||||
for ( i = 0 ; i < COMMAND_HISTORY ; i++ ) {
|
||||
Field_Clear( &kg.historyEditLines[i] );
|
||||
kg.historyEditLines[i].widthInChars = g_console_field_width;
|
||||
}
|
||||
|
||||
Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
|
||||
Cmd_AddCommand ("messagemode", Con_MessageMode_f);
|
||||
Cmd_AddCommand ("clear", Con_Clear_f);
|
||||
Cmd_AddCommand ("condump", Con_Dump_f);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
Con_Linefeed
|
||||
===============
|
||||
*/
|
||||
void Con_Linefeed (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
// mark time for transparent overlay
|
||||
if (con.current >= 0)
|
||||
con.times[con.current % NUM_CON_TIMES] = cls.realtime;
|
||||
|
||||
con.x = 0;
|
||||
if (con.display == con.current)
|
||||
con.display++;
|
||||
con.current++;
|
||||
for(i=0; i<con.linewidth; i++)
|
||||
con.text[(con.current%con.totallines)*con.linewidth+i] = (ColorIndex(COLOR_WHITE)<<8) | ' ';
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CL_ConsolePrint
|
||||
|
||||
Handles cursor positioning, line wrapping, etc
|
||||
All console printing must go through this in order to be logged to disk
|
||||
If no console is visible, the text will appear at the top of the game window
|
||||
================
|
||||
*/
|
||||
void CL_ConsolePrint( char *txt ) {
|
||||
int y;
|
||||
int c, l;
|
||||
int color;
|
||||
|
||||
// for some demos we don't want to ever show anything on the console
|
||||
if ( cl_noprint && cl_noprint->integer ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!con.initialized) {
|
||||
con.color[0] =
|
||||
con.color[1] =
|
||||
con.color[2] =
|
||||
con.color[3] = 1.0f;
|
||||
con.linewidth = -1;
|
||||
Con_CheckResize ();
|
||||
con.initialized = qtrue;
|
||||
}
|
||||
|
||||
color = ColorIndex(COLOR_WHITE);
|
||||
|
||||
while ( (c = (unsigned char )*txt) != 0 ) {
|
||||
if ( Q_IsColorString( (unsigned char*) txt ) ) {
|
||||
color = ColorIndex( *(txt+1) );
|
||||
txt += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
// count word length
|
||||
for (l=0 ; l< con.linewidth ; l++) {
|
||||
if ( txt[l] <= ' ') {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// word wrap
|
||||
if (l != con.linewidth && (con.x + l >= con.linewidth) ) {
|
||||
Con_Linefeed();
|
||||
|
||||
}
|
||||
|
||||
txt++;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
Con_Linefeed ();
|
||||
break;
|
||||
case '\r':
|
||||
con.x = 0;
|
||||
break;
|
||||
default: // display character and advance
|
||||
y = con.current % con.totallines;
|
||||
con.text[y*con.linewidth+con.x] = (color << 8) | c;
|
||||
con.x++;
|
||||
if (con.x >= con.linewidth) {
|
||||
|
||||
Con_Linefeed();
|
||||
con.x = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// mark time for transparent overlay
|
||||
|
||||
if (con.current >= 0)
|
||||
con.times[con.current % NUM_CON_TIMES] = cls.realtime;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
DRAWING
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Con_DrawInput
|
||||
|
||||
Draw the editline after a ] prompt
|
||||
================
|
||||
*/
|
||||
void Con_DrawInput (void) {
|
||||
int y;
|
||||
|
||||
if ( cls.state != CA_DISCONNECTED && !(cls.keyCatchers & KEYCATCH_CONSOLE ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
y = con.vislines - ( SMALLCHAR_HEIGHT * (re.Language_IsAsian() ? 1.5 : 2) );
|
||||
|
||||
re.SetColor( con.color );
|
||||
|
||||
SCR_DrawSmallChar( con.xadjust + 1 * SMALLCHAR_WIDTH, y, ']' );
|
||||
|
||||
Field_Draw( &kg.g_consoleField, con.xadjust + 2 * SMALLCHAR_WIDTH, y,
|
||||
SCREEN_WIDTH - 3 * SMALLCHAR_WIDTH, qtrue );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Con_DrawNotify
|
||||
|
||||
Draws the last few lines of output transparently over the game top
|
||||
================
|
||||
*/
|
||||
void Con_DrawNotify (void)
|
||||
{
|
||||
int x, v;
|
||||
short *text;
|
||||
int i;
|
||||
int time;
|
||||
int skip;
|
||||
int currentColor;
|
||||
|
||||
currentColor = 7;
|
||||
re.SetColor( g_color_table[currentColor] );
|
||||
|
||||
v = 0;
|
||||
for (i= con.current-NUM_CON_TIMES+1 ; i<=con.current ; i++)
|
||||
{
|
||||
if (i < 0)
|
||||
continue;
|
||||
time = con.times[i % NUM_CON_TIMES];
|
||||
if (time == 0)
|
||||
continue;
|
||||
time = cls.realtime - time;
|
||||
if (time > con_notifytime->value*1000)
|
||||
continue;
|
||||
text = con.text + (i % con.totallines)*con.linewidth;
|
||||
|
||||
// asian language needs to use the new font system to print glyphs...
|
||||
//
|
||||
// (ignore colours since we're going to print the whole thing as one string)
|
||||
//
|
||||
if (re.Language_IsAsian())
|
||||
{
|
||||
int iFontIndex = re.RegisterFont("ocr_a"); // this seems naughty
|
||||
const float fFontScale = 0.75f*con.yadjust;
|
||||
const int iPixelHeightToAdvance = 2+(1.3/con.yadjust) * re.Font_HeightPixels(iFontIndex, fFontScale); // for asian spacing, since we don't want glyphs to touch.
|
||||
|
||||
// concat the text to be printed...
|
||||
//
|
||||
char sTemp[4096]={0}; // ott
|
||||
for (x = 0 ; x < con.linewidth ; x++)
|
||||
{
|
||||
if ( ( (text[x]>>8)&7 ) != currentColor ) {
|
||||
currentColor = (text[x]>>8)&7;
|
||||
strcat(sTemp,va("^%i", (text[x]>>8)&7) );
|
||||
}
|
||||
strcat(sTemp,va("%c",text[x] & 0xFF));
|
||||
}
|
||||
//
|
||||
// and print...
|
||||
//
|
||||
re.Font_DrawString(con.xadjust*(con.xadjust + (1*SMALLCHAR_WIDTH/*aesthetics*/)), con.yadjust*(v), sTemp, g_color_table[currentColor], iFontIndex, -1, fFontScale);
|
||||
|
||||
v += iPixelHeightToAdvance;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = 0 ; x < con.linewidth ; x++) {
|
||||
if ( ( text[x] & 0xff ) == ' ' ) {
|
||||
continue;
|
||||
}
|
||||
if ( ( (text[x]>>8)&7 ) != currentColor ) {
|
||||
currentColor = (text[x]>>8)&7;
|
||||
re.SetColor( g_color_table[currentColor] );
|
||||
}
|
||||
SCR_DrawSmallChar( con.xadjust + (x+1)*SMALLCHAR_WIDTH, v, text[x] & 0xff );
|
||||
}
|
||||
v += SMALLCHAR_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
re.SetColor( NULL );
|
||||
|
||||
// draw the chat line
|
||||
if ( cls.keyCatchers & KEYCATCH_MESSAGE )
|
||||
{
|
||||
SCR_DrawBigString (8, v, "say:", 1.0f );
|
||||
skip = 5;
|
||||
|
||||
Field_BigDraw( &chatField, skip * BIGCHAR_WIDTH, v,
|
||||
SCREEN_WIDTH - ( skip + 1 ) * BIGCHAR_WIDTH, qtrue );
|
||||
|
||||
v += BIGCHAR_HEIGHT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Con_DrawSolidConsole
|
||||
|
||||
Draws the console with the solid background
|
||||
================
|
||||
*/
|
||||
#ifndef _XBOX
|
||||
void Con_DrawSolidConsole( float frac )
|
||||
{
|
||||
int i, x, y;
|
||||
int rows;
|
||||
short *text;
|
||||
int row;
|
||||
int lines;
|
||||
int currentColor;
|
||||
|
||||
lines = cls.glconfig.vidHeight * frac;
|
||||
if (lines <= 0)
|
||||
return;
|
||||
|
||||
if (lines > cls.glconfig.vidHeight )
|
||||
lines = cls.glconfig.vidHeight;
|
||||
|
||||
// draw the background
|
||||
y = frac * SCREEN_HEIGHT - 2;
|
||||
if ( y < 1 ) {
|
||||
y = 0;
|
||||
}
|
||||
else {
|
||||
// draw the background only if fullscreen
|
||||
if ( frac != 1.0f )
|
||||
{
|
||||
vec4_t con_color;
|
||||
MAKERGBA( con_color, 0.0f, 0.0f, 0.0f, frac*con_conAlpha->value );
|
||||
re.SetColor(con_color);
|
||||
}
|
||||
else
|
||||
{
|
||||
re.SetColor(NULL);
|
||||
}
|
||||
SCR_DrawPic( 0, 0, SCREEN_WIDTH, y, cls.consoleShader);
|
||||
}
|
||||
|
||||
|
||||
const vec4_t color = { 0.509f, 0.609f, 0.847f, 1.0f};
|
||||
// draw the bottom bar and version number
|
||||
|
||||
re.SetColor( color );
|
||||
re.DrawStretchPic( 0, y, SCREEN_WIDTH, 2, 0, 0, 0, 0, cls.whiteShader );
|
||||
|
||||
i = strlen( Q3_VERSION );
|
||||
|
||||
for (x=0 ; x<i ; x++) {
|
||||
SCR_DrawSmallChar( cls.glconfig.vidWidth - ( i - x ) * SMALLCHAR_WIDTH,
|
||||
(lines-(SMALLCHAR_HEIGHT+SMALLCHAR_HEIGHT/2)), Q3_VERSION[x] );
|
||||
}
|
||||
|
||||
|
||||
// draw the text
|
||||
con.vislines = lines;
|
||||
rows = (lines-SMALLCHAR_WIDTH)/SMALLCHAR_WIDTH; // rows of text to draw
|
||||
|
||||
y = lines - (SMALLCHAR_HEIGHT*3);
|
||||
|
||||
// draw from the bottom up
|
||||
if (con.display != con.current)
|
||||
{
|
||||
// draw arrows to show the buffer is backscrolled
|
||||
re.SetColor( g_color_table[ColorIndex(COLOR_YELLOW)] );
|
||||
for (x=0 ; x<con.linewidth ; x+=4)
|
||||
SCR_DrawSmallChar( con.xadjust + (x+1)*SMALLCHAR_WIDTH, y, '^' );
|
||||
y -= SMALLCHAR_HEIGHT;
|
||||
rows--;
|
||||
}
|
||||
|
||||
row = con.display;
|
||||
|
||||
if ( con.x == 0 ) {
|
||||
row--;
|
||||
}
|
||||
|
||||
currentColor = 7;
|
||||
re.SetColor( g_color_table[currentColor] );
|
||||
|
||||
|
||||
int iFontIndexForAsian = 0; // kinda tacky, this just gets the first registered font, since Asian stuff ignores the contents anyway
|
||||
const float fFontScaleForAsian = 0.75f*con.yadjust;
|
||||
int iPixelHeightToAdvance = SMALLCHAR_HEIGHT;
|
||||
if (re.Language_IsAsian())
|
||||
{
|
||||
if (!iFontIndexForAsian)
|
||||
{
|
||||
iFontIndexForAsian = re.RegisterFont("ocr_a"); // must be a font that's used elsewhere
|
||||
}
|
||||
iPixelHeightToAdvance = (1.3/con.yadjust) * re.Font_HeightPixels(iFontIndexForAsian, fFontScaleForAsian); // for asian spacing, since we don't want glyphs to touch.
|
||||
}
|
||||
|
||||
for (i=0 ; i<rows ; i++, y -= iPixelHeightToAdvance, row--)
|
||||
{
|
||||
if (row < 0)
|
||||
break;
|
||||
if (con.current - row >= con.totallines) {
|
||||
// past scrollback wrap point
|
||||
continue;
|
||||
}
|
||||
|
||||
text = con.text + (row % con.totallines)*con.linewidth;
|
||||
|
||||
|
||||
// asian language needs to use the new font system to print glyphs...
|
||||
//
|
||||
// (ignore colours since we're going to print the whole thing as one string)
|
||||
//
|
||||
if (re.Language_IsAsian())
|
||||
{
|
||||
// concat the text to be printed...
|
||||
//
|
||||
char sTemp[4096]={0}; // ott
|
||||
for (x = 0 ; x < con.linewidth ; x++)
|
||||
{
|
||||
if ( ( (text[x]>>8)&7 ) != currentColor ) {
|
||||
currentColor = (text[x]>>8)&7;
|
||||
strcat(sTemp,va("^%i", (text[x]>>8)&7) );
|
||||
}
|
||||
strcat(sTemp,va("%c",text[x] & 0xFF));
|
||||
}
|
||||
//
|
||||
// and print...
|
||||
//
|
||||
re.Font_DrawString(con.xadjust*(con.xadjust + (1*SMALLCHAR_WIDTH/*(aesthetics)*/)), con.yadjust*(y), sTemp, g_color_table[currentColor], iFontIndexForAsian, -1, fFontScaleForAsian);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x=0 ; x<con.linewidth ; x++) {
|
||||
if ( ( text[x] & 0xff ) == ' ' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ( (text[x]>>8)&7 ) != currentColor ) {
|
||||
currentColor = (text[x]>>8)&7;
|
||||
re.SetColor( g_color_table[currentColor] );
|
||||
}
|
||||
SCR_DrawSmallChar( con.xadjust + (x+1)*SMALLCHAR_WIDTH, y, text[x] & 0xff );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draw the input prompt, user text, and cursor if desired
|
||||
Con_DrawInput ();
|
||||
|
||||
re.SetColor( NULL );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
Con_DrawConsole
|
||||
==================
|
||||
*/
|
||||
#ifndef _XBOX
|
||||
void Con_DrawConsole( void ) {
|
||||
// check for console width changes from a vid mode change
|
||||
Con_CheckResize ();
|
||||
|
||||
// if disconnected, render console full screen
|
||||
if ( cls.state == CA_DISCONNECTED ) {
|
||||
if ( !( cls.keyCatchers & KEYCATCH_UI ) ) {
|
||||
Con_DrawSolidConsole( 1.0 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( con.displayFrac ) {
|
||||
Con_DrawSolidConsole( con.displayFrac );
|
||||
} else {
|
||||
// draw notify lines
|
||||
if ( cls.state == CA_ACTIVE ) {
|
||||
Con_DrawNotify ();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
Con_RunConsole
|
||||
|
||||
Scroll it up or down
|
||||
==================
|
||||
*/
|
||||
void Con_RunConsole (void) {
|
||||
// decide on the destination height of the console
|
||||
if ( cls.keyCatchers & KEYCATCH_CONSOLE )
|
||||
con.finalFrac = 0.5; // half screen
|
||||
else
|
||||
con.finalFrac = 0; // none visible
|
||||
|
||||
// scroll towards the destination height
|
||||
if (con.finalFrac < con.displayFrac)
|
||||
{
|
||||
con.displayFrac -= con_conspeed->value*cls.realFrametime*0.001;
|
||||
if (con.finalFrac > con.displayFrac)
|
||||
con.displayFrac = con.finalFrac;
|
||||
|
||||
}
|
||||
else if (con.finalFrac > con.displayFrac)
|
||||
{
|
||||
con.displayFrac += con_conspeed->value*cls.realFrametime*0.001;
|
||||
if (con.finalFrac < con.displayFrac)
|
||||
con.displayFrac = con.finalFrac;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Con_PageUp( void ) {
|
||||
con.display -= 2;
|
||||
if ( con.current - con.display >= con.totallines ) {
|
||||
con.display = con.current - con.totallines + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Con_PageDown( void ) {
|
||||
con.display += 2;
|
||||
if (con.display > con.current) {
|
||||
con.display = con.current;
|
||||
}
|
||||
}
|
||||
|
||||
void Con_Top( void ) {
|
||||
con.display = con.totallines;
|
||||
if ( con.current - con.display >= con.totallines ) {
|
||||
con.display = con.current - con.totallines + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Con_Bottom( void ) {
|
||||
con.display = con.current;
|
||||
}
|
||||
|
||||
|
||||
void Con_Close( void ) {
|
||||
Field_Clear( &kg.g_consoleField );
|
||||
Con_ClearNotify ();
|
||||
cls.keyCatchers &= ~KEYCATCH_CONSOLE;
|
||||
con.finalFrac = 0; // none visible
|
||||
con.displayFrac = 0;
|
||||
}
|
||||
1039
code/client/cl_input.cpp
Normal file
1039
code/client/cl_input.cpp
Normal file
File diff suppressed because it is too large
Load Diff
242
code/client/cl_input_hotswap.cpp
Normal file
242
code/client/cl_input_hotswap.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
TODO: finalize item support
|
||||
|
||||
1) Make ItemSelectUp() work.
|
||||
2) Change cg.itemSelect to whatever var is used to store selected item.
|
||||
3) Make sure commands in itemCommands work in both multi & single player.
|
||||
*/
|
||||
|
||||
#include "client.h"
|
||||
#include "../cgame/cg_local.h"
|
||||
|
||||
#include "cl_input_hotswap.h"
|
||||
#include "../qcommon/xb_settings.h"
|
||||
|
||||
#define FORCESELECTTIME forcepowerSelectTime
|
||||
#define FORCESELECT forcepowerSelect
|
||||
#define INVSELECTTIME inventorySelectTime
|
||||
#define INVSELECT inventorySelect
|
||||
#define REGISTERSOUND cgi_S_RegisterSound
|
||||
#define STARTSOUND cgi_S_StartLocalSound
|
||||
#define WEAPONBINDSTR "weapon"
|
||||
|
||||
#define BIND_TIME 2000 //number of milliseconds button is held before binding
|
||||
|
||||
|
||||
const char *itemCommands[INV_MAX] = {
|
||||
"use_electrobinoculars\n",
|
||||
"use_bacta\n",
|
||||
"use_seeker\n",
|
||||
"use_goggles\n",
|
||||
"use_sentry\n",
|
||||
NULL, //goodie key
|
||||
NULL, //security key
|
||||
};
|
||||
|
||||
// Commands to issue when user presses a force-bound button
|
||||
const char *forceDownCommands[MAX_SHOWPOWERS] = {
|
||||
"force_absorb\n",
|
||||
"force_heal\n",
|
||||
"force_protect\n",
|
||||
"force_distract\n",
|
||||
|
||||
"force_speed\n",
|
||||
"force_throw\n",
|
||||
"force_pull\n",
|
||||
"force_sight\n",
|
||||
|
||||
"+force_drain\n",
|
||||
"+force_lightning\n",
|
||||
"force_rage\n",
|
||||
"+force_grip\n",
|
||||
};
|
||||
|
||||
// Commands to issue when user releases a force-bound button
|
||||
const char *forceUpCommands[MAX_SHOWPOWERS] = {
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
"-force_drain\n",
|
||||
"-force_lightning\n",
|
||||
NULL,
|
||||
"-force_grip\n",
|
||||
};
|
||||
|
||||
|
||||
HotSwapManager::HotSwapManager(int uniqueID) :
|
||||
uniqueID(uniqueID)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
||||
const char *HotSwapManager::GetBinding(void)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
sprintf(buf, "hotswap%d", uniqueID);
|
||||
cvar_t *cvar = Cvar_Get(buf, "", CVAR_ARCHIVE);
|
||||
|
||||
if(!cvar || !cvar->string[0])
|
||||
return NULL;
|
||||
|
||||
if (cvar->integer < HOTSWAP_CAT_ITEM) { // Weapon
|
||||
return va("weapon %d", cvar->integer);
|
||||
} else if (cvar->integer < HOTSWAP_CAT_FORCE) { // Item
|
||||
return itemCommands[cvar->integer - HOTSWAP_CAT_ITEM];
|
||||
} else { // Force power
|
||||
return forceDownCommands[cvar->integer - HOTSWAP_CAT_FORCE];
|
||||
}
|
||||
}
|
||||
|
||||
const char *HotSwapManager::GetBindingUp(void)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
sprintf(buf, "hotswap%d", uniqueID);
|
||||
cvar_t *cvar = Cvar_Get(buf, "", CVAR_ARCHIVE);
|
||||
|
||||
if(!cvar || !cvar->string[0])
|
||||
return NULL;
|
||||
|
||||
// Only force powers have release-commands
|
||||
if (cvar->integer < HOTSWAP_CAT_FORCE) {
|
||||
return NULL;
|
||||
} else {
|
||||
return forceUpCommands[cvar->integer - HOTSWAP_CAT_FORCE];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HotSwapManager::Bind(void)
|
||||
{
|
||||
if(WeaponSelectUp()) {
|
||||
HotSwapBind(uniqueID, HOTSWAP_CAT_WEAPON, cg.weaponSelect);
|
||||
} else if(ForceSelectUp()) {
|
||||
HotSwapBind(uniqueID, HOTSWAP_CAT_FORCE, cg.FORCESELECT);
|
||||
} else if(ItemSelectUp()) {
|
||||
HotSwapBind(uniqueID, HOTSWAP_CAT_ITEM, cg.INVSELECT);
|
||||
} else{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
noBind = true;
|
||||
STARTSOUND(REGISTERSOUND("sound/interface/update"), 0);
|
||||
}
|
||||
|
||||
|
||||
bool HotSwapManager::ForceSelectUp(void)
|
||||
{
|
||||
return cg.FORCESELECTTIME != 0 &&
|
||||
(cg.FORCESELECTTIME + WEAPON_SELECT_TIME >= cg.time);
|
||||
}
|
||||
|
||||
|
||||
bool HotSwapManager::WeaponSelectUp(void)
|
||||
{
|
||||
return cg.weaponSelectTime != 0 &&
|
||||
(cg.weaponSelectTime + WEAPON_SELECT_TIME >= cg.time);
|
||||
}
|
||||
|
||||
|
||||
bool HotSwapManager::ItemSelectUp(void)
|
||||
{
|
||||
return cg.INVSELECTTIME != 0 &&
|
||||
(cg.INVSELECTTIME + WEAPON_SELECT_TIME >= cg.time);
|
||||
}
|
||||
|
||||
|
||||
bool HotSwapManager::HUDInBindState(void)
|
||||
{
|
||||
return ForceSelectUp() || WeaponSelectUp() || ItemSelectUp();
|
||||
}
|
||||
|
||||
|
||||
void HotSwapManager::Update(void)
|
||||
{
|
||||
if(down) {
|
||||
//Increment bindTime only if HUD is in select mode.
|
||||
if(HUDInBindState()) {
|
||||
bindTime += cls.frametime;
|
||||
} else {
|
||||
|
||||
//Clear bind time.
|
||||
bindTime = 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Down long enough, bind button.
|
||||
if(!noBind && bindTime >= BIND_TIME) {
|
||||
Bind();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HotSwapManager::Execute(void)
|
||||
{
|
||||
const char *binding = GetBinding();
|
||||
if(binding) {
|
||||
Cbuf_ExecuteText(EXEC_NOW, binding);
|
||||
}
|
||||
}
|
||||
|
||||
void HotSwapManager::ExecuteUp(void)
|
||||
{
|
||||
const char *binding = GetBindingUp();
|
||||
if(binding) {
|
||||
Cbuf_ExecuteText(EXEC_NOW, binding);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HotSwapManager::SetDown(void)
|
||||
{
|
||||
//Set the down flag.
|
||||
down = true;
|
||||
|
||||
//Execute the bind if the HUD isn't up. Also, prevent re-binding!
|
||||
if(!HUDInBindState()) {
|
||||
Execute();
|
||||
noBind = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HotSwapManager::SetUp(void)
|
||||
{
|
||||
// Execute the tail of the command if the HUD isn't up.
|
||||
if(!HUDInBindState()) {
|
||||
ExecuteUp();
|
||||
}
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
||||
void HotSwapManager::Reset(void)
|
||||
{
|
||||
down = false;
|
||||
bindTime = 0;
|
||||
noBind = false;
|
||||
}
|
||||
|
||||
void HotSwapBind(int buttonID, int category, int value)
|
||||
{
|
||||
char uniqueID[64];
|
||||
sprintf(uniqueID, "hotswap%d", buttonID);
|
||||
|
||||
// Add category as an offset for when we retrieve it
|
||||
Cvar_SetValue( uniqueID, value+category );
|
||||
Settings.hotswapSP[buttonID] = value+category;
|
||||
|
||||
Settings.Save();
|
||||
}
|
||||
|
||||
64
code/client/cl_input_hotswap.h
Normal file
64
code/client/cl_input_hotswap.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef __CL_INPUT_HOTSWAP_H
|
||||
#define __CL_INPUT_HOTSWAP_H
|
||||
|
||||
|
||||
#define HOTSWAP_ID_WHITE 0
|
||||
#define HOTSWAP_ID_BLACK 1
|
||||
#define HOTSWAP_ID_YELLOW 2
|
||||
|
||||
#define HOTSWAP_CAT_WEAPON 0
|
||||
#define HOTSWAP_CAT_ITEM 1024
|
||||
#define HOTSWAP_CAT_FORCE 2048
|
||||
|
||||
|
||||
class HotSwapManager
|
||||
{
|
||||
private:
|
||||
bool down; //Is the button down?
|
||||
bool noBind; //Don't bind the button.
|
||||
int bindTime; //How long the button has been down with the selection up.
|
||||
int uniqueID; //Unique ID for this button.
|
||||
|
||||
//Return the binding for the button, or NULL if none.
|
||||
const char *GetBinding(void);
|
||||
const char *GetBindingUp(void);
|
||||
|
||||
//Returns true if the weapon/force/item select screen is up.
|
||||
bool HUDInBindState(void);
|
||||
|
||||
//Returns true if the weapon/force/item select screen is up.
|
||||
bool ForceSelectUp(void);
|
||||
bool WeaponSelectUp(void);
|
||||
bool ItemSelectUp(void);
|
||||
|
||||
//Binds the button based on the current HUD selection.
|
||||
void Bind(void);
|
||||
|
||||
//Execute the current bind, if there is one.
|
||||
void Execute(void);
|
||||
void ExecuteUp(void);
|
||||
|
||||
//Reset the object to the default state.
|
||||
void Reset(void);
|
||||
|
||||
public:
|
||||
HotSwapManager(int uniqueID);
|
||||
|
||||
//Call every frame. Uses cg.frametime to increment timers.
|
||||
void Update(void);
|
||||
|
||||
//Set the button down or up.
|
||||
void SetDown(void);
|
||||
void SetUp(void);
|
||||
|
||||
//Returns true if the button is currently down.
|
||||
bool ButtonDown(void) { return down; }
|
||||
};
|
||||
|
||||
|
||||
//External bind function for sharing with UI.
|
||||
extern void HotSwapBind(int buttonID, int category, int value);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
1479
code/client/cl_keys.cpp
Normal file
1479
code/client/cl_keys.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1629
code/client/cl_main.cpp
Normal file
1629
code/client/cl_main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
554
code/client/cl_mp3.cpp
Normal file
554
code/client/cl_mp3.cpp
Normal file
@@ -0,0 +1,554 @@
|
||||
// Filename:- cl_mp3.cpp
|
||||
//
|
||||
// (The interface module between all the MP3 stuff and Trek)
|
||||
//
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
#include "client.h"
|
||||
#include "cl_mp3.h" // only included directly by a few snd_xxxx.cpp files plus this one
|
||||
#include "../mp3code/mp3struct.h" // keep this rather awful file secret from the rest of the program
|
||||
#include "../mp3code/copyright.h"
|
||||
|
||||
// expects data already loaded, filename arg is for error printing only
|
||||
//
|
||||
// returns success/fail
|
||||
//
|
||||
qboolean MP3_IsValid( const char *psLocalFilename, void *pvData, int iDataLen, qboolean bStereoDesired /* = qfalse */)
|
||||
{
|
||||
char *psError = C_MP3_IsValid(pvData, iDataLen, bStereoDesired);
|
||||
|
||||
if (psError)
|
||||
{
|
||||
Com_Printf(va(S_COLOR_RED"%s(%s)\n",psError, psLocalFilename));
|
||||
}
|
||||
|
||||
return !psError;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// expects data already loaded, filename arg is for error printing only
|
||||
//
|
||||
// returns unpacked length, or 0 for errors (which will be printed internally)
|
||||
//
|
||||
int MP3_GetUnpackedSize( const char *psLocalFilename, void *pvData, int iDataLen, qboolean qbIgnoreID3Tag /* = qfalse */
|
||||
, qboolean bStereoDesired /* = qfalse */
|
||||
)
|
||||
{
|
||||
int iUnpackedSize = 0;
|
||||
|
||||
// always do this now that we have fast-unpack code for measuring output size... (much safer than relying on tags that may have been edited, or if MP3 has been re-saved with same tag)
|
||||
//
|
||||
if (1)//qbIgnoreID3Tag || !MP3_ReadSpecialTagInfo((byte *)pvData, iDataLen, NULL, &iUnpackedSize))
|
||||
{
|
||||
char *psError = C_MP3_GetUnpackedSize( pvData, iDataLen, &iUnpackedSize, bStereoDesired);
|
||||
|
||||
if (psError)
|
||||
{
|
||||
Com_Printf(va(S_COLOR_RED"%s\n(File: %s)\n",psError, psLocalFilename));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return iUnpackedSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// expects data already loaded, filename arg is for error printing only
|
||||
//
|
||||
// returns byte count of unpacked data (effectively a success/fail bool)
|
||||
//
|
||||
int MP3_UnpackRawPCM( const char *psLocalFilename, void *pvData, int iDataLen, byte *pbUnpackBuffer, qboolean bStereoDesired /* = qfalse */)
|
||||
{
|
||||
int iUnpackedSize;
|
||||
char *psError = C_MP3_UnpackRawPCM( pvData, iDataLen, &iUnpackedSize, pbUnpackBuffer, bStereoDesired);
|
||||
|
||||
if (psError)
|
||||
{
|
||||
Com_Printf(va(S_COLOR_RED"%s\n(File: %s)\n",psError, psLocalFilename));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iUnpackedSize;
|
||||
}
|
||||
|
||||
|
||||
// psLocalFilename is just for error reporting (if any)...
|
||||
//
|
||||
qboolean MP3Stream_InitPlayingTimeFields( LP_MP3STREAM lpMP3Stream, const char *psLocalFilename, void *pvData, int iDataLen, qboolean bStereoDesired /* = qfalse */)
|
||||
{
|
||||
qboolean bRetval = qfalse;
|
||||
|
||||
int iRate, iWidth, iChannels;
|
||||
|
||||
char *psError = C_MP3_GetHeaderData(pvData, iDataLen, &iRate, &iWidth, &iChannels, bStereoDesired );
|
||||
if (psError)
|
||||
{
|
||||
Com_Printf(va(S_COLOR_RED"MP3Stream_InitPlayingTimeFields(): %s\n(File: %s)\n",psError, psLocalFilename));
|
||||
}
|
||||
else
|
||||
{
|
||||
int iUnpackLength = MP3_GetUnpackedSize( psLocalFilename, pvData, iDataLen, qfalse, // qboolean qbIgnoreID3Tag
|
||||
bStereoDesired);
|
||||
if (iUnpackLength)
|
||||
{
|
||||
lpMP3Stream->iTimeQuery_UnpackedLength = iUnpackLength;
|
||||
lpMP3Stream->iTimeQuery_SampleRate = iRate;
|
||||
lpMP3Stream->iTimeQuery_Channels = iChannels;
|
||||
lpMP3Stream->iTimeQuery_Width = iWidth;
|
||||
|
||||
bRetval = qtrue;
|
||||
}
|
||||
}
|
||||
|
||||
return bRetval;
|
||||
}
|
||||
|
||||
float MP3Stream_GetPlayingTimeInSeconds( LP_MP3STREAM lpMP3Stream )
|
||||
{
|
||||
if (lpMP3Stream->iTimeQuery_UnpackedLength) // fields initialised?
|
||||
return (float)((((double)lpMP3Stream->iTimeQuery_UnpackedLength / (double)lpMP3Stream->iTimeQuery_SampleRate) / (double)lpMP3Stream->iTimeQuery_Channels) / (double)lpMP3Stream->iTimeQuery_Width);
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float MP3Stream_GetRemainingTimeInSeconds( LP_MP3STREAM lpMP3Stream )
|
||||
{
|
||||
if (lpMP3Stream->iTimeQuery_UnpackedLength) // fields initialised?
|
||||
return (float)(((((double)(lpMP3Stream->iTimeQuery_UnpackedLength - (lpMP3Stream->iBytesDecodedTotal * (lpMP3Stream->iTimeQuery_SampleRate / dma.speed)))) / (double)lpMP3Stream->iTimeQuery_SampleRate) / (double)lpMP3Stream->iTimeQuery_Channels) / (double)lpMP3Stream->iTimeQuery_Width);
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// expects data already loaded, filename arg is for error printing only
|
||||
//
|
||||
qboolean MP3_FakeUpWAVInfo( const char *psLocalFilename, void *pvData, int iDataLen, int iUnpackedDataLength,
|
||||
int &format, int &rate, int &width, int &channels, int &samples, int &dataofs,
|
||||
qboolean bStereoDesired /* = qfalse */
|
||||
)
|
||||
{
|
||||
// some things can be done instantly...
|
||||
//
|
||||
format = 1; // 1 for MS format
|
||||
dataofs= 0; // will be 0 for me (since there's no header in the unpacked data)
|
||||
|
||||
// some things need to be read... (though the whole stereo flag thing is crap)
|
||||
//
|
||||
char *psError = C_MP3_GetHeaderData(pvData, iDataLen, &rate, &width, &channels, bStereoDesired );
|
||||
if (psError)
|
||||
{
|
||||
Com_Printf(va(S_COLOR_RED"%s\n(File: %s)\n",psError, psLocalFilename));
|
||||
}
|
||||
|
||||
// and some stuff needs calculating...
|
||||
//
|
||||
samples = iUnpackedDataLength / width;
|
||||
|
||||
return !psError;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char sKEY_MAXVOL[]="#MAXVOL"; // formerly #defines
|
||||
const char sKEY_UNCOMP[]="#UNCOMP"; // " "
|
||||
|
||||
// returns qtrue for success...
|
||||
//
|
||||
qboolean MP3_ReadSpecialTagInfo(byte *pbLoadedFile, int iLoadedFileLen,
|
||||
id3v1_1** ppTAG /* = NULL */,
|
||||
int *piUncompressedSize /* = NULL */,
|
||||
float *pfMaxVol /* = NULL */
|
||||
)
|
||||
{
|
||||
qboolean qbError = qfalse;
|
||||
|
||||
id3v1_1* pTAG = (id3v1_1*) ((pbLoadedFile+iLoadedFileLen)-sizeof(id3v1_1)); // sizeof = 128
|
||||
|
||||
if (!strncmp(pTAG->id, "TAG", 3))
|
||||
{
|
||||
// TAG found...
|
||||
//
|
||||
|
||||
// read MAXVOL key...
|
||||
//
|
||||
if (strncmp(pTAG->comment, sKEY_MAXVOL, strlen(sKEY_MAXVOL)))
|
||||
{
|
||||
qbError = qtrue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pfMaxVol)
|
||||
{
|
||||
*pfMaxVol = atof(pTAG->comment + strlen(sKEY_MAXVOL));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// read UNCOMP key...
|
||||
//
|
||||
if (strncmp(pTAG->album, sKEY_UNCOMP, strlen(sKEY_UNCOMP)))
|
||||
{
|
||||
qbError = qtrue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( piUncompressedSize)
|
||||
{
|
||||
*piUncompressedSize = atoi(pTAG->album + strlen(sKEY_UNCOMP));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pTAG = NULL;
|
||||
}
|
||||
|
||||
if (ppTAG)
|
||||
{
|
||||
*ppTAG = pTAG;
|
||||
}
|
||||
|
||||
return (pTAG && !qbError);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define FUZZY_AMOUNT (5*1024) // so it has to be significantly over, not just break even, because of
|
||||
// the xtra CPU time versus memory saving
|
||||
|
||||
cvar_t* cv_MP3overhead = NULL;
|
||||
void MP3_InitCvars(void)
|
||||
{
|
||||
cv_MP3overhead = Cvar_Get("s_mp3overhead", va("%d", sizeof(MP3STREAM) + FUZZY_AMOUNT), CVAR_ARCHIVE );
|
||||
}
|
||||
|
||||
|
||||
// a file has been loaded in memory, see if we want to keep it as MP3, else as normal WAV...
|
||||
//
|
||||
// return = qtrue if keeping as MP3
|
||||
//
|
||||
// (note: the reason I pass in the unpacked size rather than working it out here is simply because I already have it)
|
||||
//
|
||||
qboolean MP3Stream_InitFromFile( sfx_t* sfx, byte *pbSrcData, int iSrcDatalen, const char *psSrcDataFilename,
|
||||
int iMP3UnPackedSize, qboolean bStereoDesired /* = qfalse */
|
||||
)
|
||||
{
|
||||
// first, make a decision based on size here as to whether or not it's worth it because of MP3 buffer space
|
||||
// making small files much bigger (and therefore best left as WAV)...
|
||||
//
|
||||
|
||||
if (cv_MP3overhead &&
|
||||
(
|
||||
//iSrcDatalen + sizeof(MP3STREAM) + FUZZY_AMOUNT < iMP3UnPackedSize
|
||||
iSrcDatalen + cv_MP3overhead->integer < iMP3UnPackedSize
|
||||
)
|
||||
)
|
||||
{
|
||||
// ok, let's keep it as MP3 then...
|
||||
//
|
||||
float fMaxVol = 128; // seems to be a reasonable typical default for maxvol (for lip synch). Naturally there's no #define I can use instead...
|
||||
|
||||
MP3_ReadSpecialTagInfo(pbSrcData, iSrcDatalen, NULL, NULL, &fMaxVol ); // try and read a read maxvol from MP3 header
|
||||
|
||||
// fill in some sfx_t fields...
|
||||
//
|
||||
// Q_strncpyz( sfx->name, psSrcDataFilename, sizeof(sfx->name) );
|
||||
sfx->eSoundCompressionMethod = ct_MP3;
|
||||
sfx->fVolRange = fMaxVol;
|
||||
//sfx->width = 2;
|
||||
sfx->iSoundLengthInSamples = ((iMP3UnPackedSize / 2/*sfx->width*/) / (44100 / dma.speed)) / (bStereoDesired?2:1);
|
||||
//
|
||||
// alloc mem for data and store it (raw MP3 in this case)...
|
||||
//
|
||||
sfx->pSoundData = (short *) SND_malloc( iSrcDatalen, sfx );
|
||||
memcpy( sfx->pSoundData, pbSrcData, iSrcDatalen );
|
||||
|
||||
// now init the low-level MP3 stuff...
|
||||
//
|
||||
MP3STREAM SFX_MP3Stream = {0}; // important to init to all zeroes!
|
||||
char *psError = C_MP3Stream_DecodeInit( &SFX_MP3Stream, /*sfx->data*/ /*sfx->soundData*/ pbSrcData, iSrcDatalen,
|
||||
dma.speed,//(s_khz->value == 44)?44100:(s_khz->value == 22)?22050:11025,
|
||||
2/*sfx->width*/ * 8,
|
||||
bStereoDesired
|
||||
);
|
||||
SFX_MP3Stream.pbSourceData = (byte *) sfx->pSoundData;
|
||||
if (psError)
|
||||
{
|
||||
// This should never happen, since any errors or problems with the MP3 file would have stopped us getting
|
||||
// to this whole function, but just in case...
|
||||
//
|
||||
Com_Printf(va(S_COLOR_YELLOW"File \"%s\": %s\n",psSrcDataFilename,psError));
|
||||
|
||||
// This will leave iSrcDatalen bytes on the hunk stack (since you can't dealloc that), but MP3 files are
|
||||
// usually small, and like I say, it should never happen.
|
||||
//
|
||||
// Strictly speaking, I should do a Z_Malloc above, then I could do a Z_Free if failed, else do a Hunk_Alloc
|
||||
// to copy the Z_Malloc data into, then Z_Free, but for something that shouldn't happen it seemed bad to
|
||||
// penalise the rest of the game with extra alloc demands.
|
||||
//
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// success ( ...on a plate).
|
||||
//
|
||||
// make a copy of the filled-in stream struct and attach to the sfx_t struct...
|
||||
//
|
||||
sfx->pMP3StreamHeader = (MP3STREAM *) Z_Malloc( sizeof(MP3STREAM), TAG_SND_MP3STREAMHDR, qfalse );
|
||||
memcpy( sfx->pMP3StreamHeader, &SFX_MP3Stream, sizeof(MP3STREAM) );
|
||||
//
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// decode one packet of MP3 data only (typical output size is 2304, or 2304*2 for stereo, so input size is less
|
||||
//
|
||||
// return is decoded byte count, else 0 for finished
|
||||
//
|
||||
int MP3Stream_Decode( LP_MP3STREAM lpMP3Stream, qboolean bDoingMusic )
|
||||
{
|
||||
lpMP3Stream->iCopyOffset = 0;
|
||||
|
||||
if (0)//!bDoingMusic)
|
||||
{
|
||||
/*
|
||||
// SOF2: need to make a local buffer up so we can decode the piece we want from a contiguous bitstream rather than
|
||||
// this linklist junk...
|
||||
//
|
||||
// since MP3 packets are generally 416 or 417 bytes in length it seems reasonable to just find which linked-chunk
|
||||
// the current read offset lies within then grab the next one as well (since they're 2048 bytes) and make one
|
||||
// buffer with just the two concat'd together. Shouldn't be much of a processor hit.
|
||||
//
|
||||
sndBuffer *pChunk = (sndBuffer *) lpMP3Stream->pbSourceData;
|
||||
//
|
||||
// may as well make this static to avoid cut down on stack-validation run-time...
|
||||
//
|
||||
static byte byRawBuffer[SND_CHUNK_SIZE_BYTE*2]; // *2 for byte->short // easily enough to decode one frame of MP3 data, most are 416 or 417 bytes
|
||||
|
||||
// fast-forward to the correct chunk...
|
||||
//
|
||||
int iBytesToSkipPast = lpMP3Stream->iSourceReadIndex;
|
||||
|
||||
while (iBytesToSkipPast >= SND_CHUNK_SIZE_BYTE)
|
||||
{
|
||||
pChunk = pChunk->next;
|
||||
if (!pChunk)
|
||||
{
|
||||
// err.... reading off the end of the data stream guys...
|
||||
//
|
||||
// pChunk = (sndBuffer *) lpMP3Stream->pbSourceData; // restart
|
||||
return 0; // ... 0 bytes decoded, so will just stop caller-decoder all nice and legal as EOS
|
||||
}
|
||||
iBytesToSkipPast -= SND_CHUNK_SIZE_BYTE;
|
||||
}
|
||||
|
||||
{
|
||||
// ok, pChunk is now the 2k or so chunk we're in the middle of...
|
||||
//
|
||||
int iChunk1BytesToCopy = SND_CHUNK_SIZE_BYTE - iBytesToSkipPast;
|
||||
memcpy(byRawBuffer,((byte *)pChunk->sndChunk) + iBytesToSkipPast, iChunk1BytesToCopy);
|
||||
//
|
||||
// concat next chunk on to this as well...
|
||||
//
|
||||
pChunk = pChunk->next;
|
||||
if (pChunk)
|
||||
{
|
||||
memcpy(byRawBuffer + iChunk1BytesToCopy, pChunk->sndChunk, SND_CHUNK_SIZE_BYTE);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(byRawBuffer + iChunk1BytesToCopy, 0, SND_CHUNK_SIZE_BYTE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
// now we need to backup some struct fields, fake 'em, do the lo-level call, then restore 'em...
|
||||
//
|
||||
byte *pbSourceData_Old = lpMP3Stream->pbSourceData;
|
||||
int iSourceReadIndex_Old= lpMP3Stream->iSourceReadIndex;
|
||||
|
||||
lpMP3Stream->pbSourceData = &byRawBuffer[0];
|
||||
lpMP3Stream->iSourceReadIndex= 0; // since this is zero, not the buffer offset within a chunk, we can play tricks further down when restoring
|
||||
|
||||
{
|
||||
unsigned int uiBytesDecoded = C_MP3Stream_Decode( lpMP3Stream, qfalse );
|
||||
|
||||
lpMP3Stream->iSourceReadIndex += iSourceReadIndex_Old; // note '+=' rather than '=', to take account of movement.
|
||||
lpMP3Stream->pbSourceData = pbSourceData_Old;
|
||||
|
||||
return uiBytesDecoded;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// SOF2 music, or EF1 anything...
|
||||
//
|
||||
return C_MP3Stream_Decode( lpMP3Stream, qfalse ); // bFastForwarding
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
qboolean MP3Stream_SeekTo( channel_t *ch, float fTimeToSeekTo )
|
||||
{
|
||||
const float fEpsilon = 0.05f; // accurate to 1/50 of a second, but plus or minus this gives 1/10 of second
|
||||
|
||||
MP3Stream_Rewind( ch );
|
||||
//
|
||||
// sanity... :-)
|
||||
//
|
||||
const float fTrackLengthInSeconds = MP3Stream_GetPlayingTimeInSeconds( &ch->MP3StreamHeader );
|
||||
if (fTimeToSeekTo > fTrackLengthInSeconds)
|
||||
{
|
||||
fTimeToSeekTo = fTrackLengthInSeconds;
|
||||
}
|
||||
|
||||
// now do the seek...
|
||||
//
|
||||
while (1)
|
||||
{
|
||||
float fPlayingTimeElapsed = MP3Stream_GetPlayingTimeInSeconds( &ch->MP3StreamHeader ) - MP3Stream_GetRemainingTimeInSeconds( &ch->MP3StreamHeader );
|
||||
float fAbsTimeDiff = fabs(fTimeToSeekTo - fPlayingTimeElapsed);
|
||||
|
||||
if ( fAbsTimeDiff <= fEpsilon)
|
||||
return qtrue;
|
||||
|
||||
// when decoding, use fast-forward until within 3 seconds, then slow-decode (which should init stuff properly?)...
|
||||
//
|
||||
int iBytesDecodedThisPacket = C_MP3Stream_Decode( &ch->MP3StreamHeader, (fAbsTimeDiff > 3.0f) ); // bFastForwarding
|
||||
if (iBytesDecodedThisPacket == 0)
|
||||
break; // EOS
|
||||
}
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
|
||||
// returns qtrue for all ok
|
||||
//
|
||||
qboolean MP3Stream_Rewind( channel_t *ch )
|
||||
{
|
||||
ch->iMP3SlidingDecodeWritePos = 0;
|
||||
ch->iMP3SlidingDecodeWindowPos= 0;
|
||||
|
||||
/*
|
||||
char *psError = C_MP3Stream_Rewind( &ch->MP3StreamHeader );
|
||||
|
||||
if (psError)
|
||||
{
|
||||
Com_Printf(S_COLOR_YELLOW"%s\n",psError);
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
return qtrue;
|
||||
*/
|
||||
|
||||
// speed opt, since I know I already have the right data setup here...
|
||||
//
|
||||
memcpy(&ch->MP3StreamHeader, ch->thesfx->pMP3StreamHeader, sizeof(ch->MP3StreamHeader));
|
||||
return qtrue;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// returns qtrue while still playing normally, else qfalse for either finished or request-offset-error
|
||||
//
|
||||
qboolean MP3Stream_GetSamples( channel_t *ch, int startingSampleNum, int count, short *buf, qboolean bStereo )
|
||||
{
|
||||
qboolean qbStreamStillGoing = qtrue;
|
||||
|
||||
const int iQuarterOfSlidingBuffer = sizeof(ch->MP3SlidingDecodeBuffer)/4;
|
||||
const int iThreeQuartersOfSlidingBuffer = (sizeof(ch->MP3SlidingDecodeBuffer)*3)/4;
|
||||
|
||||
// Com_Printf("startingSampleNum %d\n",startingSampleNum);
|
||||
|
||||
count *= 2/* <- = SOF2; ch->sfx->width*/; // count arg was for words, so double it for bytes;
|
||||
|
||||
// convert sample number into a byte offset... (make new variable for clarity?)
|
||||
//
|
||||
startingSampleNum *= 2 /* <- = SOF2; ch->sfx->width*/ * (bStereo?2:1);
|
||||
|
||||
if ( startingSampleNum < ch->iMP3SlidingDecodeWindowPos)
|
||||
{
|
||||
// what?!?!?! smegging time travel needed or something?, forget it
|
||||
memset(buf,0,count);
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// OutputDebugString(va("\nRequest: startingSampleNum %d, count %d\n",startingSampleNum,count));
|
||||
// OutputDebugString(va("WindowPos %d, WindowWritePos %d\n",ch->iMP3SlidingDecodeWindowPos,ch->iMP3SlidingDecodeWritePos));
|
||||
|
||||
// qboolean _bDecoded = qfalse;
|
||||
|
||||
while (!
|
||||
(
|
||||
(startingSampleNum >= ch->iMP3SlidingDecodeWindowPos)
|
||||
&&
|
||||
(startingSampleNum + count < ch->iMP3SlidingDecodeWindowPos + ch->iMP3SlidingDecodeWritePos)
|
||||
)
|
||||
)
|
||||
{
|
||||
// if (!_bDecoded)
|
||||
// {
|
||||
// Com_Printf(S_COLOR_YELLOW"Decode needed!\n");
|
||||
// }
|
||||
// _bDecoded = qtrue;
|
||||
// OutputDebugString("Scrolling...");
|
||||
|
||||
int _iBytesDecoded = MP3Stream_Decode( (LP_MP3STREAM) &ch->MP3StreamHeader, bStereo ); // stereo only for music, so this is safe
|
||||
// OutputDebugString(va("%d bytes decoded\n",_iBytesDecoded));
|
||||
if (_iBytesDecoded == 0)
|
||||
{
|
||||
// no more source data left so clear the remainder of the buffer...
|
||||
//
|
||||
memset(ch->MP3SlidingDecodeBuffer + ch->iMP3SlidingDecodeWritePos, 0, sizeof(ch->MP3SlidingDecodeBuffer)-ch->iMP3SlidingDecodeWritePos);
|
||||
// OutputDebugString("Finished\n");
|
||||
qbStreamStillGoing = qfalse;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(ch->MP3SlidingDecodeBuffer + ch->iMP3SlidingDecodeWritePos,ch->MP3StreamHeader.bDecodeBuffer,_iBytesDecoded);
|
||||
|
||||
ch->iMP3SlidingDecodeWritePos += _iBytesDecoded;
|
||||
|
||||
// if reached 3/4 of buffer pos, backscroll the decode window by one quarter...
|
||||
//
|
||||
if (ch->iMP3SlidingDecodeWritePos > iThreeQuartersOfSlidingBuffer)
|
||||
{
|
||||
memmove(ch->MP3SlidingDecodeBuffer, ((byte *)ch->MP3SlidingDecodeBuffer + iQuarterOfSlidingBuffer), iThreeQuartersOfSlidingBuffer);
|
||||
ch->iMP3SlidingDecodeWritePos -= iQuarterOfSlidingBuffer;
|
||||
ch->iMP3SlidingDecodeWindowPos+= iQuarterOfSlidingBuffer;
|
||||
}
|
||||
}
|
||||
// OutputDebugString(va("WindowPos %d, WindowWritePos %d\n",ch->iMP3SlidingDecodeWindowPos,ch->iMP3SlidingDecodeWritePos));
|
||||
}
|
||||
|
||||
// if (!_bDecoded)
|
||||
// {
|
||||
// Com_Printf(S_COLOR_YELLOW"No decode needed\n");
|
||||
// }
|
||||
|
||||
assert(startingSampleNum >= ch->iMP3SlidingDecodeWindowPos);
|
||||
memcpy( buf, ch->MP3SlidingDecodeBuffer + (startingSampleNum-ch->iMP3SlidingDecodeWindowPos), count);
|
||||
|
||||
// OutputDebugString("OK\n\n");
|
||||
|
||||
return qbStreamStillGoing;
|
||||
}
|
||||
|
||||
|
||||
///////////// eof /////////////
|
||||
|
||||
87
code/client/cl_mp3.h
Normal file
87
code/client/cl_mp3.h
Normal file
@@ -0,0 +1,87 @@
|
||||
// Filename:- cl_mp3.h
|
||||
//
|
||||
// (Interface to the rest of the game for the MP3 functions)
|
||||
//
|
||||
#ifndef CL_MP3_H
|
||||
#define CL_MP3_H
|
||||
|
||||
|
||||
#ifndef sfx_t
|
||||
#include "snd_local.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef struct id3v1_1 {
|
||||
char id[3];
|
||||
char title[30]; // <file basename>
|
||||
char artist[30]; // "Raven Software"
|
||||
char album[30]; // "#UNCOMP %d" // needed
|
||||
char year[4]; // "2000"
|
||||
char comment[28]; // "#MAXVOL %g" // needed
|
||||
char zero;
|
||||
char track;
|
||||
char genre;
|
||||
} id3v1_1; // 128 bytes in size
|
||||
|
||||
|
||||
extern const char sKEY_MAXVOL[];
|
||||
extern const char sKEY_UNCOMP[];
|
||||
|
||||
|
||||
// (so far, all these functions are only called from one place in snd_mem.cpp)
|
||||
//
|
||||
// (filenames are used purely for error reporting, all files should already be loaded before you get here)
|
||||
//
|
||||
void MP3_InitCvars ( void );
|
||||
qboolean MP3_IsValid ( const char *psLocalFilename, void *pvData, int iDataLen, qboolean bStereoDesired = qfalse );
|
||||
int MP3_GetUnpackedSize ( const char *psLocalFilename, void *pvData, int iDataLen, qboolean qbIgnoreID3Tag = qfalse, qboolean bStereoDesired = qfalse );
|
||||
qboolean MP3_UnpackRawPCM ( const char *psLocalFilename, void *pvData, int iDataLen, byte *pbUnpackBuffer, qboolean bStereoDesired = qfalse );
|
||||
qboolean MP3Stream_InitPlayingTimeFields( LP_MP3STREAM lpMP3Stream, const char *psLocalFilename, void *pvData, int iDataLen, qboolean bStereoDesired = qfalse);
|
||||
float MP3Stream_GetPlayingTimeInSeconds( LP_MP3STREAM lpMP3Stream );
|
||||
float MP3Stream_GetRemainingTimeInSeconds( LP_MP3STREAM lpMP3Stream );
|
||||
qboolean MP3_FakeUpWAVInfo ( const char *psLocalFilename, void *pvData, int iDataLen, int iUnpackedDataLength, int &format, int &rate, int &width, int &channels, int &samples, int &dataofs, qboolean bStereoDesired = qfalse );
|
||||
qboolean MP3_ReadSpecialTagInfo ( byte *pbLoadedFile, int iLoadedFileLen,
|
||||
id3v1_1** ppTAG = NULL, int *piUncompressedSize = NULL, float *pfMaxVol = NULL);
|
||||
qboolean MP3Stream_InitFromFile ( sfx_t* sfx, byte *pbSrcData, int iSrcDatalen, const char *psSrcDataFilename, int iMP3UnPackedSize, qboolean bStereoDesired = qfalse );
|
||||
int MP3Stream_Decode ( LP_MP3STREAM lpMP3Stream, qboolean bDoingMusic );
|
||||
qboolean MP3Stream_SeekTo ( channel_t *ch, float fTimeToSeekTo );
|
||||
qboolean MP3Stream_Rewind ( channel_t *ch );
|
||||
qboolean MP3Stream_GetSamples ( channel_t *ch, int startingSampleNum, int count, short *buf, qboolean bStereo );
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////
|
||||
//
|
||||
// the real worker code deep down in the MP3 C code... (now externalised here so the music streamer can access one)
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
char* C_MP3_IsValid (void *pvData, int iDataLen, int bStereoDesired);
|
||||
char* C_MP3_GetUnpackedSize (void *pvData, int iDataLen, int *piUnpackedSize, int bStereoDesired);
|
||||
char* C_MP3_UnpackRawPCM (void *pvData, int iDataLen, int *piUnpackedSize, void *pbUnpackBuffer, int bStereoDesired);
|
||||
char* C_MP3_GetHeaderData (void *pvData, int iDataLen, int *piRate, int *piWidth, int *piChannels, int bStereoDesired);
|
||||
char* C_MP3Stream_DecodeInit (LP_MP3STREAM pSFX_MP3Stream, void *pvSourceData, int iSourceBytesRemaining,
|
||||
int iGameAudioSampleRate, int iGameAudioSampleBits, int bStereoDesired);
|
||||
unsigned int C_MP3Stream_Decode( LP_MP3STREAM pSFX_MP3Stream, int bFastForwarding );
|
||||
char* C_MP3Stream_Rewind (LP_MP3STREAM pSFX_MP3Stream);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
//
|
||||
///////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#endif // #ifndef CL_MP3_H
|
||||
|
||||
///////////////// eof /////////////////////
|
||||
|
||||
419
code/client/cl_mp3.org
Normal file
419
code/client/cl_mp3.org
Normal file
@@ -0,0 +1,419 @@
|
||||
// Filename:- cl_mp3.cpp
|
||||
//
|
||||
// (The interface module between all the MP3 stuff and Trek)
|
||||
//
|
||||
#include "client.h"
|
||||
#include "cl_mp3.h" //(only included directly from snd_mem.cpp, so not in client.h)
|
||||
#include "../mp3code/mp3struct.h" // keep this rather awful file secret from the rest of the program
|
||||
|
||||
// call the real worker code in the messy C stuff...
|
||||
//
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
char* C_MP3_IsValid (void *pvData, int iDataLen);
|
||||
char* C_MP3_GetUnpackedSize (void *pvData, int iDataLen, int *piUnpackedSize);
|
||||
char* C_MP3_UnpackRawPCM (void *pvData, int iDataLen, int *piUnpackedSize, void *pbUnpackBuffer);
|
||||
char* C_MP3_GetHeaderData (void *pvData, int iDataLen, int *piRate, int *piWidth, int *piChannels);
|
||||
char* C_MP3Stream_DecodeInit (LP_MP3STREAM pSFX_MP3Stream, void *pvSourceData, int iSourceBytesRemaining,
|
||||
int iGameAudioSampleRate, int iGameAudioSampleBits );
|
||||
unsigned int C_MP3Stream_Decode (LP_MP3STREAM pSFX_MP3Stream);
|
||||
char* C_MP3Stream_Rewind (LP_MP3STREAM pSFX_MP3Stream);
|
||||
|
||||
|
||||
// these two are temp and will eventually be deleted... honest...
|
||||
//
|
||||
char* C_TEST_MP3_GetUnpackedSize( const char *_FILENAME1, const char *_FILENAME2, const char *_FILENAME3,
|
||||
void *data1,void *data2,void *data3,
|
||||
int size1,int size2,int size3,
|
||||
int *iUnpackedSize1,int *iUnpackedSize2,int *iUnpackedSize3
|
||||
);
|
||||
char * C_TEST_MP3_UnpackRawPCM(const char *_FILENAME1, const char *_FILENAME2, const char *_FILENAME3,
|
||||
void *data1,void *data2,void *data3,
|
||||
int iSourceBytesRemaining1,int iSourceBytesRemaining2,int iSourceBytesRemaining3,
|
||||
int *piUnpackedSize1,int *piUnpackedSize2,int *piUnpackedSize3,
|
||||
void *pbUnpackBuffer1,void *pbUnpackBuffer2,void *pbUnpackBuffer3
|
||||
);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// expects data already loaded, filename arg is for error printing only
|
||||
//
|
||||
// returns success/fail
|
||||
//
|
||||
qboolean MP3_IsValid( const char *psLocalFilename, void *pvData, int iDataLen )
|
||||
{
|
||||
char *psError = C_MP3_IsValid(pvData, iDataLen);
|
||||
|
||||
if (psError)
|
||||
{
|
||||
Com_Printf(va(S_COLOR_RED"%s\n(File: %s)\n",psError, psLocalFilename));
|
||||
}
|
||||
|
||||
return !psError;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// expects data already loaded, filename arg is for error printing only
|
||||
//
|
||||
// returns unpacked length, or 0 for errors (which will be printed internally)
|
||||
//
|
||||
int MP3_GetUnpackedSize( const char *psLocalFilename, void *pvData, int iDataLen, qboolean qbIgnoreID3Tag /* = qfalse */)
|
||||
{
|
||||
int iUnpackedSize = 0;
|
||||
|
||||
if (qbIgnoreID3Tag || !MP3_ReadSpecialTagInfo((byte *)pvData, iDataLen, NULL, &iUnpackedSize))
|
||||
{
|
||||
char *psError = C_MP3_GetUnpackedSize( pvData, iDataLen, &iUnpackedSize);
|
||||
|
||||
if (psError)
|
||||
{
|
||||
Com_Printf(va(S_COLOR_RED"%s\n(File: %s)\n",psError, psLocalFilename));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return iUnpackedSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// expects data already loaded, filename arg is for error printing only
|
||||
//
|
||||
// returns byte count of unpacked data (effectively a success/fail bool)
|
||||
//
|
||||
int MP3_UnpackRawPCM( const char *psLocalFilename, void *pvData, int iDataLen, byte *pbUnpackBuffer )
|
||||
{
|
||||
int iUnpackedSize;
|
||||
char *psError = C_MP3_UnpackRawPCM( pvData, iDataLen, &iUnpackedSize, pbUnpackBuffer);
|
||||
|
||||
if (psError)
|
||||
{
|
||||
Com_Printf(va(S_COLOR_RED"%s\n(File: %s)\n",psError, psLocalFilename));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iUnpackedSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// expects data already loaded, filename arg is for error printing only
|
||||
//
|
||||
qboolean MP3_FakeUpWAVInfo( const char *psLocalFilename, void *pvData, int iDataLen, int iUnpackedDataLength, int &format, int &rate, int &width, int &channels, int &samples, int &dataofs)
|
||||
{
|
||||
// some things can be done instantly...
|
||||
//
|
||||
format = 1; // 1 for MS format
|
||||
dataofs= 0; // will be 0 for me (since there's no header in the unpacked data)
|
||||
|
||||
// some things need to be read...
|
||||
//
|
||||
char *psError = C_MP3_GetHeaderData(pvData, iDataLen, &rate, &width, &channels);
|
||||
if (psError)
|
||||
{
|
||||
Com_Printf(va(S_COLOR_RED"%s\n(File: %s)\n",psError, psLocalFilename));
|
||||
}
|
||||
|
||||
// and some stuff needs calculating...
|
||||
//
|
||||
samples = iUnpackedDataLength / width;
|
||||
|
||||
|
||||
return !psError;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char sKEY_MAXVOL[]="#MAXVOL"; // formerly #defines
|
||||
const char sKEY_UNCOMP[]="#UNCOMP"; // " "
|
||||
|
||||
// returns qtrue for success...
|
||||
//
|
||||
qboolean MP3_ReadSpecialTagInfo(byte *pbLoadedFile, int iLoadedFileLen, // (in)
|
||||
id3v1_1** ppTAG, // (out), can be NULL
|
||||
int *piUncompressedSize, float *pfMaxVol // (out), can be NULL
|
||||
)
|
||||
{
|
||||
qboolean qbError = qfalse;
|
||||
|
||||
id3v1_1* pTAG = (id3v1_1*) ((pbLoadedFile+iLoadedFileLen)-sizeof(id3v1_1)); // sizeof = 128
|
||||
|
||||
if (!strncmp(pTAG->id, "TAG", 3))
|
||||
{
|
||||
// TAG found...
|
||||
//
|
||||
|
||||
// read MAXVOL key...
|
||||
//
|
||||
if (strncmp(pTAG->comment, sKEY_MAXVOL, strlen(sKEY_MAXVOL)))
|
||||
{
|
||||
qbError = qtrue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( pfMaxVol)
|
||||
{
|
||||
*pfMaxVol = atof(pTAG->comment + strlen(sKEY_MAXVOL));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// read UNCOMP key...
|
||||
//
|
||||
if (strncmp(pTAG->album, sKEY_UNCOMP, strlen(sKEY_UNCOMP)))
|
||||
{
|
||||
qbError = qtrue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( piUncompressedSize)
|
||||
{
|
||||
*piUncompressedSize = atoi(pTAG->album + strlen(sKEY_UNCOMP));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pTAG = NULL;
|
||||
}
|
||||
|
||||
if (ppTAG)
|
||||
{
|
||||
*ppTAG = pTAG;
|
||||
}
|
||||
|
||||
return (pTAG && !qbError);
|
||||
}
|
||||
|
||||
|
||||
|
||||
qboolean TEST_MP3_GetUnpackedSize(const char *_FILENAME1, const char *_FILENAME2, const char *_FILENAME3,
|
||||
void *data1,void *data2,void *data3,
|
||||
int size1,int size2,int size3,
|
||||
int *iUnpackedSize1,int *iUnpackedSize2,int *iUnpackedSize3
|
||||
)
|
||||
{
|
||||
char *psError = C_TEST_MP3_GetUnpackedSize(_FILENAME1, _FILENAME2, _FILENAME3,
|
||||
data1,data2,data3,
|
||||
size1,size2,size3,
|
||||
iUnpackedSize1,iUnpackedSize2,iUnpackedSize3
|
||||
);
|
||||
|
||||
if (psError)
|
||||
{
|
||||
Com_Printf(va(S_COLOR_RED"%s\n",psError));
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
||||
// expects data already loaded, filename arg is for error printing only
|
||||
//
|
||||
// returns byte count of unpacked data (effectively a success/fail bool)
|
||||
//
|
||||
qboolean TEST_MP3_UnpackRawPCM( const char *_FILENAME1, const char *_FILENAME2, const char *_FILENAME3,
|
||||
void *data1,void *data2,void *data3,
|
||||
int iSourceBytesRemaining1,int iSourceBytesRemaining2,int iSourceBytesRemaining3,
|
||||
int *piUnpackedSize1,int *piUnpackedSize2,int *piUnpackedSize3,
|
||||
void *pbUnpackBuffer1,void *pbUnpackBuffer2,void *pbUnpackBuffer3
|
||||
)
|
||||
{
|
||||
char *psError = C_TEST_MP3_UnpackRawPCM(_FILENAME1, _FILENAME2, _FILENAME3,
|
||||
data1,data2,data3,
|
||||
iSourceBytesRemaining1,iSourceBytesRemaining2,iSourceBytesRemaining3,
|
||||
piUnpackedSize1,piUnpackedSize2,piUnpackedSize3,
|
||||
pbUnpackBuffer1,pbUnpackBuffer2,pbUnpackBuffer3
|
||||
);
|
||||
if (psError)
|
||||
{
|
||||
Com_Printf(va(S_COLOR_RED"%s\n",psError));
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// a file has been loaded in memory, see if we want to keep it as MP3, else as normal WAV...
|
||||
//
|
||||
// return = qtrue if keeping as MP3
|
||||
//
|
||||
// (note: the reason I pass in the unpacked size rather than working it out here is simply because I already have it)
|
||||
//
|
||||
qboolean MP3Stream_InitFromFile( sfx_t* sfx, byte *pbSrcData, int iSrcDatalen, const char *psSrcDataFilename, int iMP3UnPackedSize )
|
||||
{
|
||||
// first, make a decision based on size here as to whether or not it's worth it because of MP3 buffer space
|
||||
// making small files much bigger (and therefore best left as WAV)...
|
||||
//
|
||||
#define FUZZY_AMOUNT (5*1024) // so it has to be significantly over, not just break even, because of
|
||||
// the xtra CPU time versus memory saving
|
||||
|
||||
if (iSrcDatalen + sizeof(MP3STREAM) + FUZZY_AMOUNT < iMP3UnPackedSize)
|
||||
{
|
||||
// ok, let's keep it as MP3 then...
|
||||
//
|
||||
|
||||
float fMaxVol = 128; // seems to be a reasonable typical default for maxvol (for lip synch). Naturally there's no #define I can use instead...
|
||||
|
||||
MP3_ReadSpecialTagInfo(pbSrcData, iSrcDatalen, NULL, NULL, &fMaxVol ); // try and read a read maxvol from MP3 header
|
||||
|
||||
// fill in some sfx_t fields...
|
||||
//
|
||||
sfx->eCompressionType = ct_MP3;
|
||||
sfx->data = (byte*) Hunk_Alloc( iSrcDatalen ); // will err_drop if fails
|
||||
memcpy ( sfx->data, pbSrcData, iSrcDatalen ); // ... so the -> data field is MP3, not PCM
|
||||
sfx->width = 2;//(s_compression->value == 1)?1:2;
|
||||
sfx->length = (iMP3UnPackedSize / sfx->width) / (44100 / dma.speed);
|
||||
sfx->vol_range = fMaxVol;
|
||||
|
||||
// now init the low-level MP3 stuff...
|
||||
//
|
||||
MP3STREAM SFX_MP3Stream = {0};
|
||||
char *psError = C_MP3Stream_DecodeInit( &SFX_MP3Stream, sfx->data, iSrcDatalen,
|
||||
dma.speed,//(s_khz->value == 44)?44100:(s_khz->value == 22)?22050:11025,
|
||||
sfx->width * 8
|
||||
);
|
||||
if (psError)
|
||||
{
|
||||
// This should never happen, since any errors or problems with the MP3 file would have stopped us getting
|
||||
// to this whole function, but just in case...
|
||||
//
|
||||
Com_Printf(va(S_COLOR_YELLOW"File \"%s\": %s\n",psSrcDataFilename,psError));
|
||||
|
||||
// This will leave iSrcDatalen bytes on the hunk stack (since you can't dealloc that), but MP3 files are
|
||||
// usually small, and like I say, it should never happen.
|
||||
//
|
||||
// Strictly speaking, I should do a Z_Malloc above, then I could do a Z_Free if failed, else do a Hunk_Alloc
|
||||
// to copy the Z_Malloc data into, then Z_Free, but for something that shouldn't happen it seemed bad to
|
||||
// penalise the rest of the game with extra malloc demands.
|
||||
//
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
// success ( ...on a plate).
|
||||
//
|
||||
// make a copy of the filled-in stream struct and attach to the sfx_t struct...
|
||||
//
|
||||
sfx->pMP3StreamHeader = (MP3STREAM *) Hunk_Alloc( sizeof(MP3STREAM) );
|
||||
memcpy( sfx->pMP3StreamHeader, &SFX_MP3Stream, sizeof(MP3STREAM) );
|
||||
//
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
|
||||
// return is decoded byte count, else 0 for finished
|
||||
//
|
||||
int MP3Stream_Decode( LP_MP3STREAM lpMP3Stream )
|
||||
{
|
||||
lpMP3Stream->iCopyOffset = 0;
|
||||
return C_MP3Stream_Decode( lpMP3Stream );
|
||||
}
|
||||
|
||||
// returns qtrue for all ok
|
||||
//
|
||||
// (this can be optimised by copying the whole header from the sfx struct sometime)
|
||||
//
|
||||
qboolean MP3Stream_Rewind( channel_t *ch )
|
||||
{
|
||||
/* char *psError = C_MP3Stream_Rewind( lpMP3Stream );
|
||||
|
||||
if (psError)
|
||||
{
|
||||
Com_Printf(S_COLOR_YELLOW"%s\n",psError);
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
return qtrue;
|
||||
*/
|
||||
memcpy(&ch->MP3StreamHeader, ch->sfx->pMP3StreamHeader, sizeof(ch->MP3StreamHeader));
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
void MP3Stream_GetSamples( channel_t *ch, int startingSampleNum, int count, short *buf )
|
||||
{
|
||||
static const int iQuarterOfSlidingBuffer = sizeof(ch->MP3SlidingDecodeBuffer)/4;
|
||||
static const int iThreeQuartersOfSlidingBuffer = (sizeof(ch->MP3SlidingDecodeBuffer)*3)/4;
|
||||
|
||||
// Com_Printf("startingSampleNum %d\n",startingSampleNum);
|
||||
|
||||
count *= ch->sfx->width; // count arg was for words, so double it for bytes;
|
||||
|
||||
startingSampleNum *= ch->sfx->width;
|
||||
|
||||
if ( startingSampleNum < ch->iMP3SlidingDecodeWindowPos)
|
||||
{
|
||||
// what?!?!?! Fucking time travel needed or something?, forget it
|
||||
memset(buf,0,count);
|
||||
return;
|
||||
}
|
||||
|
||||
// OutputDebugString(va("\nRequest: startingSampleNum %d, count %d\n",startingSampleNum,count));
|
||||
// OutputDebugString(va("WindowPos %d, WindowWritePos %d\n",ch->iMP3SlidingDecodeWindowPos,ch->iMP3SlidingDecodeWritePos));
|
||||
|
||||
while (!
|
||||
(
|
||||
(startingSampleNum >= ch->iMP3SlidingDecodeWindowPos)
|
||||
&&
|
||||
(startingSampleNum + count < ch->iMP3SlidingDecodeWindowPos + ch->iMP3SlidingDecodeWritePos)
|
||||
)
|
||||
)
|
||||
{
|
||||
// OutputDebugString("Scrolling...");
|
||||
|
||||
int _iBytesDecoded = MP3Stream_Decode( (LP_MP3STREAM) &ch->MP3StreamHeader );
|
||||
// OutputDebugString(va("%d bytes decoded\n",_iBytesDecoded));
|
||||
if (_iBytesDecoded == 0)
|
||||
{
|
||||
// no more source data left so clear the remainder of the buffer...
|
||||
//
|
||||
memset(ch->MP3SlidingDecodeBuffer + ch->iMP3SlidingDecodeWritePos, 0, sizeof(ch->MP3SlidingDecodeBuffer)-ch->iMP3SlidingDecodeWritePos);
|
||||
//MP3Stream_Rewind(ch); // should I do this???
|
||||
// OutputDebugString("Finished\n");
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(ch->MP3SlidingDecodeBuffer + ch->iMP3SlidingDecodeWritePos,ch->MP3StreamHeader.bDecodeBuffer,_iBytesDecoded);
|
||||
|
||||
ch->iMP3SlidingDecodeWritePos += _iBytesDecoded;
|
||||
|
||||
// if reached 3/4 of buffer pos, backscroll the decode window by one quarter...
|
||||
//
|
||||
if (ch->iMP3SlidingDecodeWritePos > (sizeof(ch->MP3SlidingDecodeBuffer)*3)/4)
|
||||
{
|
||||
memmove(ch->MP3SlidingDecodeBuffer, ((byte *)ch->MP3SlidingDecodeBuffer + (sizeof(ch->MP3SlidingDecodeBuffer)/4)), (sizeof(ch->MP3SlidingDecodeBuffer)*3)/4);
|
||||
ch->iMP3SlidingDecodeWritePos -= sizeof(ch->MP3SlidingDecodeBuffer)/4;
|
||||
ch->iMP3SlidingDecodeWindowPos+= sizeof(ch->MP3SlidingDecodeBuffer)/4;
|
||||
}
|
||||
}
|
||||
// OutputDebugString(va("WindowPos %d, WindowWritePos %d\n",ch->iMP3SlidingDecodeWindowPos,ch->iMP3SlidingDecodeWritePos));
|
||||
}
|
||||
|
||||
assert(startingSampleNum >= ch->iMP3SlidingDecodeWindowPos);
|
||||
memcpy( buf, ch->MP3SlidingDecodeBuffer + (startingSampleNum-ch->iMP3SlidingDecodeWindowPos), count);
|
||||
|
||||
|
||||
// OutputDebugString("OK\n");
|
||||
}
|
||||
|
||||
|
||||
///////////// eof /////////////
|
||||
|
||||
510
code/client/cl_parse.cpp
Normal file
510
code/client/cl_parse.cpp
Normal file
@@ -0,0 +1,510 @@
|
||||
// cl_parse.c -- parse a message received from the server
|
||||
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
#include "client.h"
|
||||
#include "client_ui.h"
|
||||
|
||||
char *svc_strings[256] = {
|
||||
"svc_bad",
|
||||
|
||||
"svc_nop",
|
||||
"svc_gamestate",
|
||||
"svc_configstring",
|
||||
"svc_baseline",
|
||||
"svc_serverCommand",
|
||||
"svc_download",
|
||||
"svc_snapshot"
|
||||
};
|
||||
|
||||
void SHOWNET( msg_t *msg, char *s) {
|
||||
if ( cl_shownet->integer >= 2) {
|
||||
Com_Printf ("%3i:%s\n", msg->readcount-1, s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=========================================================================
|
||||
|
||||
MESSAGE PARSING
|
||||
|
||||
=========================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
==================
|
||||
CL_DeltaEntity
|
||||
|
||||
Parses deltas from the given base and adds the resulting entity
|
||||
to the current frame
|
||||
==================
|
||||
*/
|
||||
void CL_DeltaEntity (msg_t *msg, clSnapshot_t *frame)
|
||||
{
|
||||
entityState_t *state;
|
||||
|
||||
// save the parsed entity state into the big circular buffer so
|
||||
// it can be used as the source for a later delta
|
||||
state = &cl.parseEntities[cl.parseEntitiesNum & (MAX_PARSE_ENTITIES-1)];
|
||||
|
||||
MSG_ReadEntity( msg, state);
|
||||
|
||||
if ( state->number == (MAX_GENTITIES-1) ) {
|
||||
return; // entity was delta removed
|
||||
}
|
||||
cl.parseEntitiesNum++;
|
||||
frame->numEntities++;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CL_ParsePacketEntities
|
||||
|
||||
==================
|
||||
*/
|
||||
void CL_ParsePacketEntities( msg_t *msg, clSnapshot_t *oldframe, clSnapshot_t *newframe) {
|
||||
int newnum;
|
||||
entityState_t *oldstate;
|
||||
int oldindex, oldnum;
|
||||
|
||||
newframe->parseEntitiesNum = cl.parseEntitiesNum;
|
||||
newframe->numEntities = 0;
|
||||
|
||||
// delta from the entities present in oldframe
|
||||
oldindex = 0;
|
||||
oldstate = NULL;
|
||||
if (!oldframe) {
|
||||
oldnum = 99999;
|
||||
} else {
|
||||
if ( oldindex >= oldframe->numEntities ) {
|
||||
oldnum = 99999;
|
||||
} else {
|
||||
oldstate = &cl.parseEntities[
|
||||
(oldframe->parseEntitiesNum + oldindex) & (MAX_PARSE_ENTITIES-1)];
|
||||
oldnum = oldstate->number;
|
||||
}
|
||||
}
|
||||
|
||||
while ( 1 ) {
|
||||
// read the entity index number
|
||||
newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
|
||||
|
||||
if ( newnum == (MAX_GENTITIES-1) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( msg->readcount > msg->cursize ) {
|
||||
Com_Error (ERR_DROP,"CL_ParsePacketEntities: end of message");
|
||||
}
|
||||
|
||||
while ( oldnum < newnum ) {
|
||||
// one or more entities from the old packet are unchanged
|
||||
if ( cl_shownet->integer == 3 ) {
|
||||
Com_Printf ("%3i: unchanged: %i\n", msg->readcount, oldnum);
|
||||
}
|
||||
CL_DeltaEntity( msg, newframe );
|
||||
|
||||
oldindex++;
|
||||
|
||||
if ( oldindex >= oldframe->numEntities ) {
|
||||
oldnum = 99999;
|
||||
} else {
|
||||
oldstate = &cl.parseEntities[
|
||||
(oldframe->parseEntitiesNum + oldindex) & (MAX_PARSE_ENTITIES-1)];
|
||||
oldnum = oldstate->number;
|
||||
}
|
||||
}
|
||||
if (oldnum == newnum) {
|
||||
// delta from previous state
|
||||
if ( cl_shownet->integer == 3 ) {
|
||||
Com_Printf ("%3i: delta: %i\n", msg->readcount, newnum);
|
||||
}
|
||||
CL_DeltaEntity( msg, newframe );
|
||||
|
||||
oldindex++;
|
||||
|
||||
if ( oldindex >= oldframe->numEntities ) {
|
||||
oldnum = 99999;
|
||||
} else {
|
||||
oldstate = &cl.parseEntities[
|
||||
(oldframe->parseEntitiesNum + oldindex) & (MAX_PARSE_ENTITIES-1)];
|
||||
oldnum = oldstate->number;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( oldnum > newnum ) {
|
||||
// delta from baseline
|
||||
if ( cl_shownet->integer == 3 ) {
|
||||
Com_Printf ("%3i: baseline: %i\n", msg->readcount, newnum);
|
||||
}
|
||||
CL_DeltaEntity( msg, newframe );
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// any remaining entities in the old frame are copied over
|
||||
while ( oldnum != 99999 ) {
|
||||
// one or more entities from the old packet are unchanged
|
||||
if ( cl_shownet->integer == 3 ) {
|
||||
Com_Printf ("%3i: unchanged: %i\n", msg->readcount, oldnum);
|
||||
}
|
||||
CL_DeltaEntity( msg, newframe );
|
||||
|
||||
oldindex++;
|
||||
|
||||
if ( oldindex >= oldframe->numEntities ) {
|
||||
oldnum = 99999;
|
||||
} else {
|
||||
oldstate = &cl.parseEntities[
|
||||
(oldframe->parseEntitiesNum + oldindex) & (MAX_PARSE_ENTITIES-1)];
|
||||
oldnum = oldstate->number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
CL_ParseSnapshot
|
||||
|
||||
If the snapshot is parsed properly, it will be copied to
|
||||
cl.frame and saved in cl.frames[]. If the snapshot is invalid
|
||||
for any reason, no changes to the state will be made at all.
|
||||
================
|
||||
*/
|
||||
void CL_ParseSnapshot( msg_t *msg ) {
|
||||
int len;
|
||||
clSnapshot_t *old;
|
||||
clSnapshot_t newSnap;
|
||||
int deltaNum;
|
||||
int oldMessageNum;
|
||||
int i, packetNum;
|
||||
|
||||
// get the reliable sequence acknowledge number
|
||||
clc.reliableAcknowledge = MSG_ReadLong( msg );
|
||||
|
||||
// read in the new snapshot to a temporary buffer
|
||||
// we will only copy to cl.frame if it is valid
|
||||
memset (&newSnap, 0, sizeof(newSnap));
|
||||
|
||||
newSnap.serverCommandNum = clc.serverCommandSequence;
|
||||
newSnap.serverTime = MSG_ReadLong( msg );
|
||||
newSnap.messageNum = MSG_ReadLong( msg );
|
||||
deltaNum = MSG_ReadByte( msg );
|
||||
if ( !deltaNum ) {
|
||||
newSnap.deltaNum = -1;
|
||||
} else {
|
||||
newSnap.deltaNum = newSnap.messageNum - deltaNum;
|
||||
}
|
||||
newSnap.cmdNum = MSG_ReadLong( msg );
|
||||
newSnap.snapFlags = MSG_ReadByte( msg );
|
||||
|
||||
// If the frame is delta compressed from data that we
|
||||
// no longer have available, we must suck up the rest of
|
||||
// the frame, but not use it, then ask for a non-compressed
|
||||
// message
|
||||
if ( newSnap.deltaNum <= 0 ) {
|
||||
newSnap.valid = qtrue; // uncompressed frame
|
||||
old = NULL;
|
||||
} else {
|
||||
old = &cl.frames[newSnap.deltaNum & PACKET_MASK];
|
||||
if ( !old->valid ) {
|
||||
// should never happen
|
||||
Com_Printf ("Delta from invalid frame (not supposed to happen!).\n");
|
||||
} else if ( old->messageNum != newSnap.deltaNum ) {
|
||||
// The frame that the server did the delta from
|
||||
// is too old, so we can't reconstruct it properly.
|
||||
Com_Printf ("Delta frame too old.\n");
|
||||
} else if ( cl.parseEntitiesNum - old->parseEntitiesNum > MAX_PARSE_ENTITIES ) {
|
||||
Com_Printf ("Delta parseEntitiesNum too old.\n");
|
||||
} else {
|
||||
newSnap.valid = qtrue; // valid delta parse
|
||||
}
|
||||
}
|
||||
|
||||
// read areamask
|
||||
len = MSG_ReadByte( msg );
|
||||
MSG_ReadData( msg, &newSnap.areamask, len);
|
||||
|
||||
// read playerinfo
|
||||
SHOWNET( msg, "playerstate" );
|
||||
if ( old ) {
|
||||
MSG_ReadDeltaPlayerstate( msg, &old->ps, &newSnap.ps );
|
||||
} else {
|
||||
MSG_ReadDeltaPlayerstate( msg, NULL, &newSnap.ps );
|
||||
}
|
||||
|
||||
// read packet entities
|
||||
SHOWNET( msg, "packet entities" );
|
||||
CL_ParsePacketEntities( msg, old, &newSnap );
|
||||
|
||||
// if not valid, dump the entire thing now that it has
|
||||
// been properly read
|
||||
if ( !newSnap.valid ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// clear the valid flags of any snapshots between the last
|
||||
// received and this one
|
||||
oldMessageNum = cl.frame.messageNum + 1;
|
||||
|
||||
if ( cl.frame.messageNum - oldMessageNum >= PACKET_BACKUP ) {
|
||||
oldMessageNum = cl.frame.messageNum - ( PACKET_BACKUP - 1 );
|
||||
}
|
||||
for ( ; oldMessageNum < newSnap.messageNum ; oldMessageNum++ ) {
|
||||
cl.frames[oldMessageNum & PACKET_MASK].valid = qfalse;
|
||||
}
|
||||
|
||||
// copy to the current good spot
|
||||
cl.frame = newSnap;
|
||||
|
||||
// calculate ping time
|
||||
for ( i = 0 ; i < PACKET_BACKUP ; i++ ) {
|
||||
packetNum = ( clc.netchan.outgoingSequence - 1 - i ) & PACKET_MASK;
|
||||
if ( cl.frame.cmdNum == cl.packetCmdNumber[ packetNum ] ) {
|
||||
cl.frame.ping = cls.realtime - cl.packetTime[ packetNum ];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// save the frame off in the backup array for later delta comparisons
|
||||
cl.frames[cl.frame.messageNum & PACKET_MASK] = cl.frame;
|
||||
|
||||
if (cl_shownet->integer == 3) {
|
||||
Com_Printf (" frame:%i delta:%i\n", cl.frame.messageNum,
|
||||
cl.frame.deltaNum);
|
||||
}
|
||||
|
||||
// actions for valid frames
|
||||
cl.newSnapshots = qtrue;
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
CL_SystemInfoChanged
|
||||
|
||||
The systeminfo configstring has been changed, so parse
|
||||
new information out of it. This will happen at every
|
||||
gamestate, and possibly during gameplay.
|
||||
==================
|
||||
*/
|
||||
void CL_SystemInfoChanged( void ) {
|
||||
char *systemInfo;
|
||||
const char *s;
|
||||
char key[MAX_INFO_KEY];
|
||||
char value[MAX_INFO_VALUE];
|
||||
|
||||
systemInfo = cl.gameState.stringData + cl.gameState.stringOffsets[ CS_SYSTEMINFO ];
|
||||
cl.serverId = atoi( Info_ValueForKey( systemInfo, "sv_serverid" ) );
|
||||
|
||||
s = Info_ValueForKey( systemInfo, "helpUsObi" );
|
||||
if ( atoi(s) == 0 ) {
|
||||
Cvar_SetCheatState();
|
||||
}
|
||||
|
||||
// scan through all the variables in the systeminfo and locally set cvars to match
|
||||
s = systemInfo;
|
||||
while ( s ) {
|
||||
Info_NextPair( &s, key, value );
|
||||
if ( !key[0] ) {
|
||||
break;
|
||||
}
|
||||
|
||||
Cvar_Set( key, value );
|
||||
}
|
||||
//if ( Cvar_VariableIntegerValue("ui_iscensored") == 1 )
|
||||
//{
|
||||
// Cvar_Set( "g_dismemberment", "0");
|
||||
//}
|
||||
}
|
||||
|
||||
void UI_UpdateConnectionString( char *string );
|
||||
|
||||
/*
|
||||
==================
|
||||
CL_ParseGamestate
|
||||
==================
|
||||
*/
|
||||
void CL_ParseGamestate( msg_t *msg ) {
|
||||
int i;
|
||||
int cmd;
|
||||
char *s;
|
||||
|
||||
Con_Close();
|
||||
|
||||
UI_UpdateConnectionString( "" );
|
||||
|
||||
// wipe local client state
|
||||
CL_ClearState();
|
||||
|
||||
// a gamestate always marks a server command sequence
|
||||
clc.serverCommandSequence = MSG_ReadLong( msg );
|
||||
|
||||
// parse all the configstrings and baselines
|
||||
cl.gameState.dataCount = 1; // leave a 0 at the beginning for uninitialized configstrings
|
||||
while ( 1 ) {
|
||||
cmd = MSG_ReadByte( msg );
|
||||
|
||||
if ( cmd <= 0 ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( cmd == svc_configstring ) {
|
||||
int len;
|
||||
|
||||
i = MSG_ReadShort( msg );
|
||||
if ( i < 0 || i >= MAX_CONFIGSTRINGS ) {
|
||||
Com_Error( ERR_DROP, "configstring > MAX_CONFIGSTRINGS" );
|
||||
}
|
||||
s = MSG_ReadString( msg );
|
||||
len = strlen( s );
|
||||
|
||||
if ( len + 1 + cl.gameState.dataCount > MAX_GAMESTATE_CHARS ) {
|
||||
Com_Error( ERR_DROP, "MAX_GAMESTATE_CHARS exceeded" );
|
||||
}
|
||||
|
||||
// append it to the gameState string buffer
|
||||
cl.gameState.stringOffsets[ i ] = cl.gameState.dataCount;
|
||||
memcpy( cl.gameState.stringData + cl.gameState.dataCount, s, len + 1 );
|
||||
cl.gameState.dataCount += len + 1;
|
||||
if ( cl_shownet->integer == 3 ) {
|
||||
Com_Printf ("%3i: CS# %d %s (%d)\n",msg->readcount, i,s,len);
|
||||
}
|
||||
} else if ( cmd == svc_baseline ) {
|
||||
assert(0);
|
||||
} else {
|
||||
Com_Error( ERR_DROP, "CL_ParseGamestate: bad command byte" );
|
||||
}
|
||||
}
|
||||
|
||||
// parse serverId and other cvars
|
||||
CL_SystemInfoChanged();
|
||||
|
||||
// reinitialize the filesystem if the game directory has changed
|
||||
#if 0
|
||||
if ( fs_game->modified ) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// let the client game init and load data
|
||||
cls.state = CA_LOADING;
|
||||
|
||||
CL_StartHunkUsers();
|
||||
|
||||
// make sure the game starts
|
||||
Cvar_Set( "cl_paused", "0" );
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================
|
||||
|
||||
void CL_FreeServerCommands(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<MAX_RELIABLE_COMMANDS; i++) {
|
||||
if ( clc.serverCommands[ i ] ) {
|
||||
Z_Free( clc.serverCommands[ i ] );
|
||||
clc.serverCommands[ i ] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
CL_ParseCommandString
|
||||
|
||||
Command strings are just saved off until cgame asks for them
|
||||
when it transitions a snapshot
|
||||
=====================
|
||||
*/
|
||||
void CL_ParseCommandString( msg_t *msg ) {
|
||||
char *s;
|
||||
int seq;
|
||||
int index;
|
||||
|
||||
seq = MSG_ReadLong( msg );
|
||||
s = MSG_ReadString( msg );
|
||||
|
||||
// see if we have already executed stored it off
|
||||
if ( clc.serverCommandSequence >= seq ) {
|
||||
return;
|
||||
}
|
||||
clc.serverCommandSequence = seq;
|
||||
|
||||
index = seq & (MAX_RELIABLE_COMMANDS-1);
|
||||
if ( clc.serverCommands[ index ] ) {
|
||||
Z_Free( clc.serverCommands[ index ] );
|
||||
}
|
||||
clc.serverCommands[ index ] = CopyString( s );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=====================
|
||||
CL_ParseServerMessage
|
||||
=====================
|
||||
*/
|
||||
void CL_ParseServerMessage( msg_t *msg ) {
|
||||
int cmd;
|
||||
|
||||
if ( cl_shownet->integer == 1 ) {
|
||||
Com_Printf ("%i ",msg->cursize);
|
||||
} else if ( cl_shownet->integer >= 2 ) {
|
||||
Com_Printf ("------------------\n");
|
||||
}
|
||||
|
||||
//
|
||||
// parse the message
|
||||
//
|
||||
while ( 1 ) {
|
||||
if ( msg->readcount > msg->cursize ) {
|
||||
Com_Error (ERR_DROP,"CL_ParseServerMessage: read past end of server message");
|
||||
break;
|
||||
}
|
||||
|
||||
cmd = MSG_ReadByte( msg );
|
||||
|
||||
if ( cmd == -1 ) {
|
||||
SHOWNET( msg, "END OF MESSAGE" );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( cl_shownet->integer >= 2 ) {
|
||||
if ( !svc_strings[cmd] ) {
|
||||
Com_Printf( "%3i:BAD CMD %i\n", msg->readcount-1, cmd );
|
||||
} else {
|
||||
SHOWNET( msg, svc_strings[cmd] );
|
||||
}
|
||||
}
|
||||
|
||||
// other commands
|
||||
switch ( cmd ) {
|
||||
default:
|
||||
Com_Error (ERR_DROP,"CL_ParseServerMessage: Illegible server message\n");
|
||||
break;
|
||||
case svc_nop:
|
||||
break;
|
||||
case svc_serverCommand:
|
||||
CL_ParseCommandString( msg );
|
||||
break;
|
||||
case svc_gamestate:
|
||||
CL_ParseGamestate( msg );
|
||||
break;
|
||||
case svc_snapshot:
|
||||
CL_ParseSnapshot( msg );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
575
code/client/cl_scrn.cpp
Normal file
575
code/client/cl_scrn.cpp
Normal file
@@ -0,0 +1,575 @@
|
||||
// cl_scrn.c -- master for refresh, status bar, console, chat, notify, etc
|
||||
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
#include "client.h"
|
||||
#include "client_ui.h"
|
||||
|
||||
extern console_t con;
|
||||
|
||||
qboolean scr_initialized; // ready to draw
|
||||
|
||||
cvar_t *cl_timegraph;
|
||||
cvar_t *cl_debuggraph;
|
||||
cvar_t *cl_graphheight;
|
||||
cvar_t *cl_graphscale;
|
||||
cvar_t *cl_graphshift;
|
||||
|
||||
/*
|
||||
================
|
||||
SCR_DrawNamedPic
|
||||
|
||||
Coordinates are 640*480 virtual values
|
||||
=================
|
||||
*/
|
||||
void SCR_DrawNamedPic( float x, float y, float width, float height, const char *picname ) {
|
||||
qhandle_t hShader;
|
||||
|
||||
assert( width != 0 );
|
||||
|
||||
hShader = re.RegisterShader( picname );
|
||||
re.DrawStretchPic( x, y, width, height, 0, 0, 1, 1, hShader );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
SCR_FillRect
|
||||
|
||||
Coordinates are 640*480 virtual values
|
||||
=================
|
||||
*/
|
||||
void SCR_FillRect( float x, float y, float width, float height, const float *color ) {
|
||||
re.SetColor( color );
|
||||
|
||||
re.DrawStretchPic( x, y, width, height, 0, 0, 0, 0, cls.whiteShader );
|
||||
|
||||
re.SetColor( NULL );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
SCR_DrawPic
|
||||
|
||||
Coordinates are 640*480 virtual values
|
||||
A width of 0 will draw with the original image width
|
||||
=================
|
||||
*/
|
||||
void SCR_DrawPic( float x, float y, float width, float height, qhandle_t hShader ) {
|
||||
re.DrawStretchPic( x, y, width, height, 0, 0, 1, 1, hShader );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** SCR_DrawBigChar
|
||||
** big chars are drawn at 640*480 virtual screen size
|
||||
*/
|
||||
void SCR_DrawBigChar( int x, int y, int ch ) {
|
||||
int row, col;
|
||||
float frow, fcol;
|
||||
float size;
|
||||
float ax, ay, aw, ah;
|
||||
|
||||
ch &= 255;
|
||||
|
||||
if ( ch == ' ' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( y < -BIGCHAR_HEIGHT ) {
|
||||
return;
|
||||
}
|
||||
|
||||
ax = x;
|
||||
ay = y;
|
||||
aw = BIGCHAR_WIDTH;
|
||||
ah = BIGCHAR_HEIGHT;
|
||||
|
||||
row = ch>>4;
|
||||
col = ch&15;
|
||||
|
||||
frow = row*0.0625;
|
||||
fcol = col*0.0625;
|
||||
size = 0.0625;
|
||||
/*
|
||||
re.DrawStretchPic( ax, ay, aw, ah,
|
||||
fcol, frow,
|
||||
fcol + size, frow + size,
|
||||
cls.charSetShader );
|
||||
*/
|
||||
float size2;
|
||||
|
||||
frow = row*0.0625;
|
||||
fcol = col*0.0625;
|
||||
size = 0.03125;
|
||||
size2 = 0.0625;
|
||||
|
||||
re.DrawStretchPic( ax, ay, aw, ah,
|
||||
fcol, frow,
|
||||
fcol + size, frow + size2,
|
||||
cls.charSetShader );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
** SCR_DrawSmallChar
|
||||
** small chars are drawn at native screen resolution
|
||||
*/
|
||||
void SCR_DrawSmallChar( int x, int y, int ch ) {
|
||||
int row, col;
|
||||
float frow, fcol;
|
||||
float size;
|
||||
|
||||
ch &= 255;
|
||||
|
||||
if ( ch == ' ' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( y < -SMALLCHAR_HEIGHT ) {
|
||||
return;
|
||||
}
|
||||
|
||||
row = ch>>4;
|
||||
col = ch&15;
|
||||
/*
|
||||
frow = row*0.0625;
|
||||
fcol = col*0.0625;
|
||||
size = 0.0625;
|
||||
|
||||
re.DrawStretchPic( x, y, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT,
|
||||
fcol, frow,
|
||||
fcol + size, frow + size,
|
||||
cls.charSetShader );
|
||||
*/
|
||||
|
||||
float size2;
|
||||
|
||||
frow = row*0.0625;
|
||||
fcol = col*0.0625;
|
||||
size = 0.03125;
|
||||
size2 = 0.0625;
|
||||
|
||||
re.DrawStretchPic( x * con.xadjust, y * con.yadjust,
|
||||
SMALLCHAR_WIDTH * con.xadjust, SMALLCHAR_HEIGHT * con.yadjust,
|
||||
fcol, frow,
|
||||
fcol + size, frow + size2,
|
||||
cls.charSetShader );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
SCR_DrawBigString[Color]
|
||||
|
||||
Draws a multi-colored string with a drop shadow, optionally forcing
|
||||
to a fixed color.
|
||||
|
||||
Coordinates are at 640 by 480 virtual resolution
|
||||
==================
|
||||
*/
|
||||
void SCR_DrawBigStringExt( int x, int y, const char *string, float *setColor, qboolean forceColor ) {
|
||||
vec4_t color;
|
||||
const char *s;
|
||||
int xx;
|
||||
|
||||
// draw the drop shadow
|
||||
color[0] = color[1] = color[2] = 0;
|
||||
color[3] = setColor[3];
|
||||
re.SetColor( color );
|
||||
s = string;
|
||||
xx = x;
|
||||
while ( *s ) {
|
||||
if ( Q_IsColorString( s ) ) {
|
||||
s += 2;
|
||||
continue;
|
||||
}
|
||||
SCR_DrawBigChar( xx+2, y+2, *s );
|
||||
xx+=16;
|
||||
s++;
|
||||
}
|
||||
|
||||
|
||||
// draw the colored text
|
||||
s = string;
|
||||
xx = x;
|
||||
re.SetColor( setColor );
|
||||
while ( *s ) {
|
||||
if ( Q_IsColorString( s ) ) {
|
||||
if ( !forceColor ) {
|
||||
memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color ) );
|
||||
color[3] = setColor[3];
|
||||
re.SetColor( color );
|
||||
}
|
||||
s += 2;
|
||||
continue;
|
||||
}
|
||||
SCR_DrawBigChar( xx, y, *s );
|
||||
xx+=16;
|
||||
s++;
|
||||
}
|
||||
re.SetColor( NULL );
|
||||
}
|
||||
|
||||
|
||||
void SCR_DrawBigString( int x, int y, const char *s, float alpha ) {
|
||||
float color[4];
|
||||
|
||||
color[0] = color[1] = color[2] = 1.0;
|
||||
color[3] = alpha;
|
||||
SCR_DrawBigStringExt( x, y, s, color, qfalse );
|
||||
}
|
||||
|
||||
void SCR_DrawBigStringColor( int x, int y, const char *s, vec4_t color ) {
|
||||
SCR_DrawBigStringExt( x, y, s, color, qtrue );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** SCR_Strlen -- skips color escape codes
|
||||
*/
|
||||
static int SCR_Strlen( const char *str ) {
|
||||
const char *s = str;
|
||||
int count = 0;
|
||||
|
||||
while ( *s ) {
|
||||
if ( Q_IsColorString( s ) ) {
|
||||
s += 2;
|
||||
} else {
|
||||
count++;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
** SCR_GetBigStringWidth
|
||||
*/
|
||||
int SCR_GetBigStringWidth( const char *str ) {
|
||||
return SCR_Strlen( str ) * 16;
|
||||
}
|
||||
|
||||
//===============================================================================
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
DEBUG GRAPH
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
#ifndef _XBOX
|
||||
typedef struct
|
||||
{
|
||||
float value;
|
||||
int color;
|
||||
} graphsamp_t;
|
||||
|
||||
static int current;
|
||||
static graphsamp_t values[1024];
|
||||
|
||||
/*
|
||||
==============
|
||||
SCR_DebugGraph
|
||||
==============
|
||||
*/
|
||||
void SCR_DebugGraph (float value, int color)
|
||||
{
|
||||
values[current&1023].value = value;
|
||||
values[current&1023].color = color;
|
||||
current++;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SCR_DrawDebugGraph
|
||||
==============
|
||||
*/
|
||||
void SCR_DrawDebugGraph (void)
|
||||
{
|
||||
int a, x, y, w, i, h;
|
||||
float v;
|
||||
int color;
|
||||
|
||||
//
|
||||
// draw the graph
|
||||
//
|
||||
w = cls.glconfig.vidWidth;
|
||||
x = 0;
|
||||
y = cls.glconfig.vidHeight;
|
||||
re.SetColor( g_color_table[0] );
|
||||
re.DrawStretchPic(x, y - cl_graphheight->integer,
|
||||
w, cl_graphheight->integer, 0, 0, 0, 0, 0 );
|
||||
re.SetColor( NULL );
|
||||
|
||||
for (a=0 ; a<w ; a++)
|
||||
{
|
||||
i = (current-1-a+1024) & 1023;
|
||||
v = values[i].value;
|
||||
color = values[i].color;
|
||||
v = v * cl_graphscale->integer + cl_graphshift->integer;
|
||||
|
||||
if (v < 0)
|
||||
v += cl_graphheight->integer * (1+(int)(-v / cl_graphheight->integer));
|
||||
h = (int)v % cl_graphheight->integer;
|
||||
re.DrawStretchPic( x+w-1-a, y - h, 1, h, 0, 0, 0, 0, 0 );
|
||||
}
|
||||
}
|
||||
#endif // _XBOX
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
SCR_Init
|
||||
==================
|
||||
*/
|
||||
void SCR_Init( void ) {
|
||||
cl_timegraph = Cvar_Get ("timegraph", "0", CVAR_CHEAT);
|
||||
cl_debuggraph = Cvar_Get ("debuggraph", "0", CVAR_CHEAT);
|
||||
cl_graphheight = Cvar_Get ("graphheight", "32", CVAR_CHEAT);
|
||||
cl_graphscale = Cvar_Get ("graphscale", "1", CVAR_CHEAT);
|
||||
cl_graphshift = Cvar_Get ("graphshift", "0", CVAR_CHEAT);
|
||||
|
||||
scr_initialized = qtrue;
|
||||
}
|
||||
|
||||
|
||||
//=======================================================
|
||||
|
||||
void UI_SetActiveMenu( const char* menuname,const char *menuID );
|
||||
void _UI_Refresh( int realtime );
|
||||
void UI_DrawConnect( const char *servername, const char * updateInfoString );
|
||||
|
||||
/*
|
||||
==================
|
||||
SCR_DrawScreenField
|
||||
|
||||
This will be called twice if rendering in stereo mode
|
||||
==================
|
||||
*/
|
||||
void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
|
||||
|
||||
re.BeginFrame( stereoFrame );
|
||||
|
||||
// wide aspect ratio screens need to have the sides cleared
|
||||
// unless they are displaying game renderings
|
||||
#ifndef _XBOX
|
||||
// Xbox no want this
|
||||
if ( cls.state != CA_ACTIVE ) {
|
||||
if ( cls.glconfig.vidWidth * 480 > cls.glconfig.vidHeight * 640 ) {
|
||||
re.SetColor( g_color_table[0] );
|
||||
re.DrawStretchPic( 0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight, 0, 0, 0, 0, 0 );
|
||||
re.SetColor( NULL );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// if the menu is going to cover the entire screen, we
|
||||
// don't need to render anything under it
|
||||
if ( !_UI_IsFullscreen() ) {
|
||||
switch( cls.state ) {
|
||||
default:
|
||||
Com_Error( ERR_FATAL, "SCR_DrawScreenField: bad cls.state" );
|
||||
break;
|
||||
case CA_CINEMATIC:
|
||||
SCR_DrawCinematic();
|
||||
break;
|
||||
case CA_DISCONNECTED:
|
||||
// force menu up
|
||||
UI_SetActiveMenu( "mainMenu",NULL ); // VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
|
||||
break;
|
||||
case CA_CONNECTING:
|
||||
case CA_CHALLENGING:
|
||||
case CA_CONNECTED:
|
||||
// connecting clients will only show the connection dialog
|
||||
UI_DrawConnect( clc.servername, cls.updateInfoString );
|
||||
break;
|
||||
case CA_LOADING:
|
||||
case CA_PRIMED:
|
||||
// We got past the time when the UI needs to prevent swapping
|
||||
extern bool connectSwapOverride;
|
||||
connectSwapOverride = false;
|
||||
|
||||
// draw the game information screen and loading progress
|
||||
CL_CGameRendering( stereoFrame );
|
||||
break;
|
||||
case CA_ACTIVE:
|
||||
if (CL_IsRunningInGameCinematic() || CL_InGameCinematicOnStandBy())
|
||||
{
|
||||
SCR_DrawCinematic();
|
||||
}
|
||||
else
|
||||
{
|
||||
CL_CGameRendering( stereoFrame );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _XBOX // on xbox this is rendered right before a flip
|
||||
re.ProcessDissolve();
|
||||
#endif // _XBOX
|
||||
|
||||
// draw downloading progress bar
|
||||
|
||||
// the menu draws next
|
||||
_UI_Refresh( cls.realtime );
|
||||
|
||||
// console draws next
|
||||
// Con_DrawConsole ();
|
||||
|
||||
// debug graph can be drawn on top of anything
|
||||
#ifndef _XBOX
|
||||
if ( cl_debuggraph->integer || cl_timegraph->integer ) {
|
||||
SCR_DrawDebugGraph ();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SCR_UpdateScreen
|
||||
|
||||
This is called every frame, and can also be called explicitly to flush
|
||||
text to the screen.
|
||||
==================
|
||||
*/
|
||||
void SCR_UpdateScreen( void ) {
|
||||
static int recursive;
|
||||
|
||||
if ( !scr_initialized ) {
|
||||
return; // not initialized yet
|
||||
}
|
||||
|
||||
// load the ref / ui / cgame if needed
|
||||
CL_StartHunkUsers();
|
||||
|
||||
if ( ++recursive > 2 ) {
|
||||
Com_Error( ERR_FATAL, "SCR_UpdateScreen: recursively called" );
|
||||
}
|
||||
recursive = qtrue;
|
||||
|
||||
// if running in stereo, we need to draw the frame twice
|
||||
if ( cls.glconfig.stereoEnabled ) {
|
||||
SCR_DrawScreenField( STEREO_LEFT );
|
||||
SCR_DrawScreenField( STEREO_RIGHT );
|
||||
} else {
|
||||
SCR_DrawScreenField( STEREO_CENTER );
|
||||
}
|
||||
|
||||
if ( com_speeds->integer ) {
|
||||
re.EndFrame( &time_frontend, &time_backend );
|
||||
} else {
|
||||
re.EndFrame( NULL, NULL );
|
||||
}
|
||||
|
||||
recursive = 0;
|
||||
}
|
||||
|
||||
// this stuff is only used by the savegame (SG) code for screenshots...
|
||||
//
|
||||
#ifdef _XBOX
|
||||
|
||||
/*
|
||||
static byte bScreenData[SG_SCR_WIDTH * SG_SCR_HEIGHT * 4];
|
||||
static qboolean screenDataValid = qfalse;
|
||||
void SCR_UnprecacheScreenshot()
|
||||
{
|
||||
screenDataValid = qfalse;
|
||||
}
|
||||
*/
|
||||
|
||||
void SCR_PrecacheScreenshot()
|
||||
{
|
||||
// No screenshots unless connected to single player local server...
|
||||
//
|
||||
// char *psInfo = cl.gameState.stringData + cl.gameState.stringOffsets[ CS_SERVERINFO ];
|
||||
// int iMaxClients = atoi(Info_ValueForKey( psInfo, "sv_maxclients" ));
|
||||
|
||||
// (no need to check single-player status in voyager, this code base is all singleplayer)
|
||||
if ( cls.state != CA_ACTIVE )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef _XBOX
|
||||
if (cls.keyCatchers == 0)
|
||||
{
|
||||
// in-game...
|
||||
//
|
||||
// SCR_UnprecacheScreenshot();
|
||||
// pbScreenData = (byte *)Z_Malloc(SG_SCR_WIDTH * SG_SCR_HEIGHT * 4);
|
||||
S_ClearSoundBuffer(); // clear DMA etc because the following glReadPixels() call can take ages
|
||||
re.GetScreenShot( (byte *) &bScreenData, SG_SCR_WIDTH, SG_SCR_HEIGHT);
|
||||
screenDataValid = qtrue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're in the console, or menu, or message input...
|
||||
//
|
||||
}
|
||||
#endif
|
||||
|
||||
// save the current screenshot to the user space to be used
|
||||
// with a savegame
|
||||
#ifdef _XBOX
|
||||
extern void SaveCompressedScreenshot( void );
|
||||
SaveCompressedScreenshot();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
byte *SCR_GetScreenshot(qboolean *qValid)
|
||||
{
|
||||
if (!screenDataValid) {
|
||||
SCR_PrecacheScreenshot();
|
||||
}
|
||||
if (qValid) {
|
||||
*qValid = screenDataValid;
|
||||
}
|
||||
return (byte *)&bScreenData;
|
||||
}
|
||||
|
||||
// called from save-game code to set the lo-res loading screen to be the one from the save file...
|
||||
//
|
||||
void SCR_SetScreenshot(const byte *pbData, int w, int h)
|
||||
{
|
||||
if (w == SG_SCR_WIDTH && h == SG_SCR_HEIGHT)
|
||||
{
|
||||
screenDataValid = qtrue;
|
||||
memcpy(&bScreenData, pbData, SG_SCR_WIDTH*SG_SCR_HEIGHT*4);
|
||||
}
|
||||
else
|
||||
{
|
||||
screenDataValid = qfalse;
|
||||
memset(&bScreenData, 0, SG_SCR_WIDTH*SG_SCR_HEIGHT*4);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// This is just a client-side wrapper for the function RE_TempRawImage_ReadFromFile() in the renderer code...
|
||||
//
|
||||
/*
|
||||
byte* SCR_TempRawImage_ReadFromFile(const char *psLocalFilename, int *piWidth, int *piHeight, byte *pbReSampleBuffer, qboolean qbVertFlip)
|
||||
{
|
||||
return re.TempRawImage_ReadFromFile(psLocalFilename, piWidth, piHeight, pbReSampleBuffer, qbVertFlip);
|
||||
}
|
||||
//
|
||||
// ditto (sort of)...
|
||||
//
|
||||
void SCR_TempRawImage_CleanUp()
|
||||
{
|
||||
re.TempRawImage_CleanUp();
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
503
code/client/cl_ui.cpp
Normal file
503
code/client/cl_ui.cpp
Normal file
@@ -0,0 +1,503 @@
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
#include "client.h"
|
||||
#include "client_ui.h"
|
||||
|
||||
#include "vmachine.h"
|
||||
|
||||
int PC_ReadTokenHandle(int handle, struct pc_token_s *pc_token);
|
||||
|
||||
int CL_UISystemCalls( int *args );
|
||||
|
||||
//prototypes
|
||||
//extern qboolean SG_GetSaveImage( const char *psPathlessBaseName, void *pvAddress );
|
||||
extern int SG_GetSaveGameComment(const char *psPathlessBaseName, char *sComment, char *sMapName);
|
||||
extern qboolean SG_GameAllowedToSaveHere(qboolean inCamera);
|
||||
extern void SG_StoreSaveGameComment(const char *sComment);
|
||||
//extern byte *SCR_GetScreenshot(qboolean *qValid);
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
Helper functions for User Interface
|
||||
====================
|
||||
*/
|
||||
|
||||
/*
|
||||
====================
|
||||
GetClientState
|
||||
====================
|
||||
*/
|
||||
static connstate_t GetClientState( void ) {
|
||||
return cls.state;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_GetGlConfig
|
||||
====================
|
||||
*/
|
||||
static void UI_GetGlconfig( glconfig_t *config ) {
|
||||
*config = cls.glconfig;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
GetClipboardData
|
||||
====================
|
||||
*/
|
||||
static void GetClipboardData( char *buf, int buflen ) {
|
||||
char *cbd;
|
||||
|
||||
cbd = Sys_GetClipboardData();
|
||||
|
||||
if ( !cbd ) {
|
||||
*buf = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Q_strncpyz( buf, cbd, buflen );
|
||||
|
||||
Z_Free( cbd );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
Key_KeynumToStringBuf
|
||||
====================
|
||||
*/
|
||||
// only ever called by binding-display code, therefore returns non-technical "friendly" names
|
||||
// in any language that don't necessarily match those in the config file...
|
||||
//
|
||||
void Key_KeynumToStringBuf( int keynum, char *buf, int buflen )
|
||||
{
|
||||
const char *psKeyName = Key_KeynumToString( keynum/*, qtrue */);
|
||||
|
||||
// see if there's a more friendly (or localised) name...
|
||||
//
|
||||
const char *psKeyNameFriendly = SE_GetString( va("KEYNAMES_KEYNAME_%s",psKeyName) );
|
||||
|
||||
Q_strncpyz( buf, (psKeyNameFriendly && psKeyNameFriendly[0]) ? psKeyNameFriendly : psKeyName, buflen );
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
Key_GetBindingBuf
|
||||
====================
|
||||
*/
|
||||
void Key_GetBindingBuf( int keynum, char *buf, int buflen ) {
|
||||
char *value;
|
||||
|
||||
value = Key_GetBinding( keynum );
|
||||
if ( value ) {
|
||||
Q_strncpyz( buf, value, buflen );
|
||||
}
|
||||
else {
|
||||
*buf = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
Key_GetCatcher
|
||||
====================
|
||||
*/
|
||||
int Key_GetCatcher( void )
|
||||
{
|
||||
return cls.keyCatchers;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
Key_GetCatcher
|
||||
====================
|
||||
*/
|
||||
void Key_SetCatcher( int catcher )
|
||||
{
|
||||
cls.keyCatchers = catcher;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
FloatAsInt
|
||||
====================
|
||||
*/
|
||||
int FloatAsInt( float f )
|
||||
{
|
||||
int temp;
|
||||
|
||||
*(float *)&temp = f;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void UI_Cvar_Create( const char *var_name, const char *var_value, int flags ) {
|
||||
Cvar_Get( var_name, var_value, flags );
|
||||
}
|
||||
|
||||
static int GetConfigString(int index, char *buf, int size)
|
||||
{
|
||||
int offset;
|
||||
|
||||
if (index < 0 || index >= MAX_CONFIGSTRINGS)
|
||||
return qfalse;
|
||||
|
||||
offset = cl.gameState.stringOffsets[index];
|
||||
if (!offset)
|
||||
return qfalse;
|
||||
|
||||
Q_strncpyz( buf, cl.gameState.stringData+offset, size);
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_ShutdownUI
|
||||
====================
|
||||
*/
|
||||
void CL_ShutdownUI( void ) {
|
||||
cls.keyCatchers &= ~KEYCATCH_UI;
|
||||
cls.uiStarted = qfalse;
|
||||
}
|
||||
|
||||
void CL_DrawDatapad(int HUDType)
|
||||
{
|
||||
switch(HUDType)
|
||||
{
|
||||
case DP_OBJECTIVES:
|
||||
VM_Call( CG_DRAW_DATAPAD_OBJECTIVES );
|
||||
break;
|
||||
case DP_WEAPONS:
|
||||
VM_Call( CG_DRAW_DATAPAD_WEAPONS );
|
||||
break;
|
||||
case DP_INVENTORY:
|
||||
VM_Call( CG_DRAW_DATAPAD_INVENTORY );
|
||||
break;
|
||||
case DP_FORCEPOWERS:
|
||||
VM_Call( CG_DRAW_DATAPAD_FORCEPOWERS );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void UI_Init( int apiVersion, uiimport_t *uiimport, qboolean inGameLoad );
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_InitUI
|
||||
====================
|
||||
*/
|
||||
void CL_InitUI( void ) {
|
||||
uiimport_t uii;
|
||||
|
||||
memset( &uii, 0, sizeof( uii ) );
|
||||
|
||||
uii.Printf = Com_Printf;
|
||||
uii.Error = Com_Error;
|
||||
|
||||
uii.Cvar_Set = Cvar_Set;
|
||||
uii.Cvar_VariableValue = Cvar_VariableValue;
|
||||
uii.Cvar_VariableStringBuffer = Cvar_VariableStringBuffer;
|
||||
uii.Cvar_SetValue = Cvar_SetValue;
|
||||
uii.Cvar_Reset = Cvar_Reset;
|
||||
uii.Cvar_Create = UI_Cvar_Create;
|
||||
uii.Cvar_InfoStringBuffer = Cvar_InfoStringBuffer;
|
||||
|
||||
uii.Draw_DataPad = CL_DrawDatapad;
|
||||
|
||||
uii.Argc = Cmd_Argc;
|
||||
uii.Argv = Cmd_ArgvBuffer;
|
||||
uii.Cmd_TokenizeString = Cmd_TokenizeString;
|
||||
|
||||
uii.Cmd_ExecuteText = Cbuf_ExecuteText;
|
||||
|
||||
uii.FS_FOpenFile = FS_FOpenFileByMode;
|
||||
uii.FS_Read = FS_Read;
|
||||
uii.FS_Write = FS_Write;
|
||||
uii.FS_FCloseFile = FS_FCloseFile;
|
||||
uii.FS_GetFileList = FS_GetFileList;
|
||||
uii.FS_ReadFile = FS_ReadFile;
|
||||
uii.FS_FreeFile = FS_FreeFile;
|
||||
|
||||
uii.R_RegisterModel = re.RegisterModel;
|
||||
uii.R_RegisterSkin = re.RegisterSkin;
|
||||
uii.R_RegisterShader = re.RegisterShader;
|
||||
uii.R_RegisterShaderNoMip = re.RegisterShaderNoMip;
|
||||
uii.R_RegisterFont = re.RegisterFont;
|
||||
#ifndef _XBOX
|
||||
uii.R_Font_StrLenPixels = re.Font_StrLenPixels;
|
||||
uii.R_Font_HeightPixels = re.Font_HeightPixels;
|
||||
uii.R_Font_DrawString = re.Font_DrawString;
|
||||
#endif
|
||||
uii.R_Font_StrLenChars = re.Font_StrLenChars;
|
||||
uii.Language_IsAsian = re.Language_IsAsian;
|
||||
uii.Language_UsesSpaces = re.Language_UsesSpaces;
|
||||
uii.AnyLanguage_ReadCharFromString = re.AnyLanguage_ReadCharFromString;
|
||||
|
||||
//uii.SG_GetSaveImage = SG_GetSaveImage;
|
||||
uii.SG_GetSaveGameComment = SG_GetSaveGameComment;
|
||||
uii.SG_StoreSaveGameComment = SG_StoreSaveGameComment;
|
||||
uii.SG_GameAllowedToSaveHere= SG_GameAllowedToSaveHere;
|
||||
|
||||
//uii.SCR_GetScreenshot = SCR_GetScreenshot;
|
||||
|
||||
//uii.DrawStretchRaw = re.DrawStretchRaw;
|
||||
uii.R_ClearScene = re.ClearScene;
|
||||
uii.R_AddRefEntityToScene = re.AddRefEntityToScene;
|
||||
uii.R_AddPolyToScene = re.AddPolyToScene;
|
||||
uii.R_AddLightToScene = re.AddLightToScene;
|
||||
uii.R_RenderScene = re.RenderScene;
|
||||
|
||||
uii.R_ModelBounds = re.ModelBounds;
|
||||
|
||||
uii.R_SetColor = re.SetColor;
|
||||
uii.R_DrawStretchPic = re.DrawStretchPic;
|
||||
uii.UpdateScreen = SCR_UpdateScreen;
|
||||
|
||||
#ifdef _XBOX
|
||||
uii.PrecacheScreenshot = SCR_PrecacheScreenshot;
|
||||
#endif
|
||||
|
||||
uii.R_LerpTag = re.LerpTag;
|
||||
|
||||
uii.S_StartLocalLoopingSound= S_StartLocalLoopingSound;
|
||||
uii.S_StartLocalSound = S_StartLocalSound;
|
||||
uii.S_RegisterSound = S_RegisterSound;
|
||||
|
||||
uii.Key_KeynumToStringBuf = Key_KeynumToStringBuf;
|
||||
uii.Key_GetBindingBuf = Key_GetBindingBuf;
|
||||
uii.Key_SetBinding = Key_SetBinding;
|
||||
uii.Key_IsDown = Key_IsDown;
|
||||
uii.Key_GetOverstrikeMode = Key_GetOverstrikeMode;
|
||||
uii.Key_SetOverstrikeMode = Key_SetOverstrikeMode;
|
||||
uii.Key_ClearStates = Key_ClearStates;
|
||||
uii.Key_GetCatcher = Key_GetCatcher;
|
||||
uii.Key_SetCatcher = Key_SetCatcher;
|
||||
|
||||
uii.GetClipboardData = GetClipboardData;
|
||||
|
||||
uii.GetClientState = GetClientState;
|
||||
|
||||
uii.GetGlconfig = UI_GetGlconfig;
|
||||
|
||||
uii.GetConfigString = (void (*)(int, char *, int))GetConfigString;
|
||||
|
||||
uii.Milliseconds = Sys_Milliseconds;
|
||||
|
||||
UI_Init(UI_API_VERSION, &uii, (cls.state > CA_DISCONNECTED && cls.state <= CA_ACTIVE));
|
||||
|
||||
//JLF MPSKIPPED
|
||||
#ifdef _XBOX
|
||||
extern void UpdateDemoTimer();
|
||||
UpdateDemoTimer();
|
||||
|
||||
#endif
|
||||
|
||||
// uie->UI_Init( UI_API_VERSION, &uii );
|
||||
|
||||
}
|
||||
|
||||
|
||||
qboolean UI_GameCommand( void ) {
|
||||
if (!cls.uiStarted)
|
||||
{
|
||||
return qfalse;
|
||||
}
|
||||
return UI_ConsoleCommand();
|
||||
}
|
||||
|
||||
|
||||
void CL_GenericMenu_f(void)
|
||||
{
|
||||
char *arg = Cmd_Argv( 1 );
|
||||
|
||||
if (cls.uiStarted) {
|
||||
UI_SetActiveMenu("ingame",arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CL_EndScreenDissolve_f(void)
|
||||
{
|
||||
re.InitDissolve(qtrue); // dissolve from cinematic to underlying ingame
|
||||
}
|
||||
|
||||
void CL_DataPad_f(void)
|
||||
{
|
||||
if (cls.uiStarted && cls.cgameStarted && (cls.state == CA_ACTIVE) ) {
|
||||
UI_SetActiveMenu("datapad",NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_GetGlConfig
|
||||
====================
|
||||
*/
|
||||
static void CL_GetGlconfig( glconfig_t *config )
|
||||
{
|
||||
*config = cls.glconfig;
|
||||
}
|
||||
/*
|
||||
int PC_ReadTokenHandle(int handle, pc_token_t *pc_token);
|
||||
int PC_SourceFileAndLine(int handle, char *filename, int *line);
|
||||
*/
|
||||
/*
|
||||
====================
|
||||
CL_UISystemCalls
|
||||
|
||||
The ui module is making a system call
|
||||
====================
|
||||
*/
|
||||
vm_t uivm;
|
||||
|
||||
#define VMA(x) ((void*)args[x])
|
||||
#define VMF(x) ((float *)args)[x]
|
||||
int CL_UISystemCalls( int *args )
|
||||
{
|
||||
|
||||
switch( args[0] )
|
||||
{
|
||||
case UI_ERROR:
|
||||
Com_Error( ERR_DROP, "%s", VMA(1) );
|
||||
return 0;
|
||||
|
||||
case UI_CVAR_REGISTER:
|
||||
Cvar_Register( (vmCvar_t *)VMA(1),(const char *) VMA(2),(const char *) VMA(3), args[4] );
|
||||
return 0;
|
||||
|
||||
case UI_CVAR_SET:
|
||||
Cvar_Set( (const char *) VMA(1), (const char *) VMA(2) );
|
||||
return 0;
|
||||
|
||||
case UI_CVAR_SETVALUE:
|
||||
Cvar_SetValue( (const char *) VMA(1), VMF(2) );
|
||||
return 0;
|
||||
|
||||
case UI_CVAR_UPDATE:
|
||||
Cvar_Update( (vmCvar_t *) VMA(1) );
|
||||
return 0;
|
||||
|
||||
case UI_R_REGISTERMODEL:
|
||||
return re.RegisterModel((const char *) VMA(1) );
|
||||
|
||||
case UI_R_REGISTERSHADERNOMIP:
|
||||
return re.RegisterShaderNoMip((const char *) VMA(1) );
|
||||
|
||||
case UI_GETGLCONFIG:
|
||||
CL_GetGlconfig( ( glconfig_t *) VMA(1) );
|
||||
return 0;
|
||||
|
||||
case UI_CMD_EXECUTETEXT:
|
||||
Cbuf_ExecuteText( args[1], (const char *) VMA(2) );
|
||||
return 0;
|
||||
|
||||
case UI_CVAR_VARIABLEVALUE:
|
||||
return FloatAsInt( Cvar_VariableValue( (const char *) VMA(1) ) );
|
||||
|
||||
case UI_FS_GETFILELIST:
|
||||
return FS_GetFileList( (const char *) VMA(1), (const char *) VMA(2), (char *) VMA(3), args[4] );
|
||||
|
||||
case UI_KEY_SETCATCHER:
|
||||
Key_SetCatcher( args[1] );
|
||||
return 0;
|
||||
|
||||
case UI_KEY_CLEARSTATES:
|
||||
Key_ClearStates();
|
||||
return 0;
|
||||
|
||||
case UI_R_SETCOLOR:
|
||||
re.SetColor( (const float *) VMA(1) );
|
||||
return 0;
|
||||
|
||||
case UI_R_DRAWSTRETCHPIC:
|
||||
re.DrawStretchPic( VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), args[9] );
|
||||
return 0;
|
||||
|
||||
case UI_CVAR_VARIABLESTRINGBUFFER:
|
||||
Cvar_VariableStringBuffer( (const char *) VMA(1), (char *) VMA(2), args[3] );
|
||||
return 0;
|
||||
|
||||
case UI_R_MODELBOUNDS:
|
||||
re.ModelBounds( args[1], (float *) VMA(2),(float *) VMA(3) );
|
||||
return 0;
|
||||
|
||||
case UI_R_CLEARSCENE:
|
||||
re.ClearScene();
|
||||
return 0;
|
||||
|
||||
// case UI_KEY_GETOVERSTRIKEMODE:
|
||||
// return Key_GetOverstrikeMode();
|
||||
// return 0;
|
||||
|
||||
// case UI_PC_READ_TOKEN:
|
||||
// return PC_ReadTokenHandle( args[1], VMA(2) );
|
||||
|
||||
// case UI_PC_SOURCE_FILE_AND_LINE:
|
||||
// return PC_SourceFileAndLine( args[1], VMA(2), VMA(3) );
|
||||
|
||||
case UI_KEY_GETCATCHER:
|
||||
return Key_GetCatcher();
|
||||
|
||||
case UI_MILLISECONDS:
|
||||
return Sys_Milliseconds();
|
||||
|
||||
case UI_S_REGISTERSOUND:
|
||||
return S_RegisterSound((const char *) VMA(1));
|
||||
|
||||
case UI_S_STARTLOCALSOUND:
|
||||
S_StartLocalSound( args[1], args[2] );
|
||||
return 0;
|
||||
|
||||
// case UI_R_REGISTERFONT:
|
||||
// re.RegisterFont( VMA(1), args[2], VMA(3));
|
||||
// return 0;
|
||||
|
||||
case UI_CIN_PLAYCINEMATIC:
|
||||
Com_DPrintf("UI_CIN_PlayCinematic\n");
|
||||
return CIN_PlayCinematic((const char *)VMA(1), args[2], args[3], args[4], args[5], args[6], (const char *)VMA(7));
|
||||
|
||||
case UI_CIN_STOPCINEMATIC:
|
||||
return CIN_StopCinematic(args[1]);
|
||||
|
||||
case UI_CIN_RUNCINEMATIC:
|
||||
return CIN_RunCinematic(args[1]);
|
||||
|
||||
#ifndef _XBOX
|
||||
case UI_CIN_DRAWCINEMATIC:
|
||||
CIN_DrawCinematic(args[1]);
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
case UI_KEY_SETBINDING:
|
||||
Key_SetBinding( args[1], (const char *) VMA(2) );
|
||||
return 0;
|
||||
|
||||
case UI_KEY_KEYNUMTOSTRINGBUF:
|
||||
Key_KeynumToStringBuf( args[1],(char *) VMA(2), args[3] );
|
||||
return 0;
|
||||
|
||||
case UI_CIN_SETEXTENTS:
|
||||
CIN_SetExtents(args[1], args[2], args[3], args[4], args[5]);
|
||||
return 0;
|
||||
|
||||
case UI_KEY_GETBINDINGBUF:
|
||||
Key_GetBindingBuf( args[1], (char *) VMA(2), args[3] );
|
||||
return 0;
|
||||
|
||||
|
||||
default:
|
||||
Com_Error( ERR_DROP, "Bad UI system trap: %i", args[0] );
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
474
code/client/client.h
Normal file
474
code/client/client.h
Normal file
@@ -0,0 +1,474 @@
|
||||
// client.h -- primary header for client
|
||||
#pragma once
|
||||
#ifndef __CLIENT_H__
|
||||
#define __CLIENT_H__
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "../renderer/tr_public.h"
|
||||
#include "keys.h"
|
||||
#include "snd_public.h"
|
||||
#include "../cgame/cg_public.h"
|
||||
|
||||
// snapshots are a view of the server at a given time
|
||||
typedef struct {
|
||||
qboolean valid; // cleared if delta parsing was invalid
|
||||
int snapFlags; // rate delayed and dropped commands
|
||||
|
||||
int serverTime; // server time the message is valid for (in msec)
|
||||
|
||||
int messageNum; // copied from netchan->incoming_sequence
|
||||
int deltaNum; // messageNum the delta is from
|
||||
int ping; // time from when cmdNum-1 was sent to time packet was reeceived
|
||||
byte areamask[MAX_MAP_AREA_BYTES]; // portalarea visibility bits
|
||||
|
||||
int cmdNum; // the next cmdNum the server is expecting
|
||||
playerState_t ps; // complete information about the current player at this time
|
||||
|
||||
int numEntities; // all of the entities that need to be presented
|
||||
int parseEntitiesNum; // at the time of this snapshot
|
||||
|
||||
int serverCommandNum; // execute all commands up to this before
|
||||
// making the snapshot current
|
||||
} clSnapshot_t;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
the clientActive_t structure is wiped completely at every
|
||||
new gamestate_t, potentially several times during an established connection
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
// the parseEntities array must be large enough to hold PACKET_BACKUP frames of
|
||||
// entities, so that when a delta compressed message arives from the server
|
||||
// it can be un-deltad from the original
|
||||
#define MAX_PARSE_ENTITIES 512
|
||||
|
||||
extern int g_console_field_width;
|
||||
|
||||
typedef struct {
|
||||
int timeoutcount;
|
||||
|
||||
clSnapshot_t frame; // latest received from server
|
||||
|
||||
int serverTime;
|
||||
int oldServerTime; // to prevent time from flowing bakcwards
|
||||
int oldFrameServerTime; // to check tournament restarts
|
||||
int serverTimeDelta; // cl.serverTime = cls.realtime + cl.serverTimeDelta
|
||||
// this value changes as net lag varies
|
||||
qboolean extrapolatedSnapshot; // set if any cgame frame has been forced to extrapolate
|
||||
// cleared when CL_AdjustTimeDelta looks at it
|
||||
qboolean newSnapshots; // set on parse, cleared when CL_AdjustTimeDelta looks at it
|
||||
|
||||
gameState_t gameState; // configstrings
|
||||
char mapname[MAX_QPATH]; // extracted from CS_SERVERINFO
|
||||
|
||||
int parseEntitiesNum; // index (not anded off) into cl_parse_entities[]
|
||||
|
||||
int mouseDx[2], mouseDy[2]; // added to by mouse events
|
||||
int mouseIndex;
|
||||
int joystickAxis[MAX_JOYSTICK_AXIS]; // set by joystick events
|
||||
|
||||
int cgameUserCmdValue; // current weapon to add to usercmd_t
|
||||
float cgameSensitivity;
|
||||
|
||||
// cmds[cmdNumber] is the predicted command, [cmdNumber-1] is the last
|
||||
// properly generated command
|
||||
usercmd_t cmds[CMD_BACKUP]; // each mesage will send several old cmds
|
||||
int cmdNumber; // incremented each frame, because multiple
|
||||
// frames may need to be packed into a single packet
|
||||
|
||||
int packetTime[PACKET_BACKUP]; // cls.realtime sent, for calculating pings
|
||||
int packetCmdNumber[PACKET_BACKUP]; // cmdNumber when packet was sent
|
||||
|
||||
// the client maintains its own idea of view angles, which are
|
||||
// sent to the server each frame. It is cleared to 0 upon entering each level.
|
||||
// the server sends a delta each frame which is added to the locally
|
||||
// tracked view angles to account for standing on rotating objects,
|
||||
// and teleport direction changes
|
||||
vec3_t viewangles;
|
||||
|
||||
// these are just parsed out of the configstrings for convenience
|
||||
int serverId;
|
||||
|
||||
// non-gameserver infornamtion
|
||||
int cinematictime; // cls.realtime for first cinematic frame (FIXME: NO LONGER USED!, but I wasn't sure if I could remove it because of struct sizes assumed elsewhere? -Ste)
|
||||
|
||||
// big stuff at end of structure so most offsets are 15 bits or less
|
||||
clSnapshot_t frames[PACKET_BACKUP];
|
||||
|
||||
entityState_t parseEntities[MAX_PARSE_ENTITIES];
|
||||
|
||||
//DJC added - making force powers in single player work like those in
|
||||
//multiplayer. This makes hot swapping code more portable.
|
||||
qboolean gcmdSendValue;
|
||||
byte gcmdValue;
|
||||
} clientActive_t;
|
||||
|
||||
extern clientActive_t cl;
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
the clientConnection_t structure is wiped when disconnecting from a server,
|
||||
either to go to a full screen console, or connect to a different server
|
||||
|
||||
A connection can be to either a server through the network layer,
|
||||
or just a streaming cinematic.
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
int lastPacketSentTime; // for retransmits
|
||||
int lastPacketTime;
|
||||
char servername[MAX_OSPATH]; // name of server from original connect
|
||||
netadr_t serverAddress;
|
||||
int connectTime; // for connection retransmits
|
||||
int connectPacketCount; // for display on connection dialog
|
||||
|
||||
int challenge; // from the server to use for connecting
|
||||
|
||||
int reliableSequence;
|
||||
int reliableAcknowledge;
|
||||
char *reliableCommands[MAX_RELIABLE_COMMANDS];
|
||||
|
||||
// reliable messages received from server
|
||||
int serverCommandSequence;
|
||||
char *serverCommands[MAX_RELIABLE_COMMANDS];
|
||||
|
||||
// big stuff at end of structure so most offsets are 15 bits or less
|
||||
netchan_t netchan;
|
||||
} clientConnection_t;
|
||||
|
||||
extern clientConnection_t clc;
|
||||
|
||||
/*
|
||||
==================================================================
|
||||
|
||||
the clientStatic_t structure is never wiped, and is used even when
|
||||
no client connection is active at all
|
||||
|
||||
==================================================================
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
EXIT_CONSOLE,
|
||||
EXIT_ARENAS,
|
||||
EXIT_SERVERS,
|
||||
EXIT_LAUNCH // quit all the way out of the game on disconnect
|
||||
} exitTo_t;
|
||||
|
||||
#ifdef _XBOX
|
||||
#define MAX_LOCAL_SERVERS 1
|
||||
#define MAX_GLOBAL_SERVERS 1
|
||||
#define MAX_PINGREQUESTS 1
|
||||
#else
|
||||
#define MAX_LOCAL_SERVERS 16
|
||||
#define MAX_GLOBAL_SERVERS 256
|
||||
#define MAX_PINGREQUESTS 16
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
netadr_t adr;
|
||||
int start;
|
||||
int time;
|
||||
} ping_t;
|
||||
|
||||
typedef struct {
|
||||
netadr_t netadr;
|
||||
char info[MAX_INFO_STRING];
|
||||
} serverInfoResponse_t;
|
||||
|
||||
typedef struct {
|
||||
netadr_t netadr;
|
||||
char info[MAX_INFO_STRING];
|
||||
} getserversResponse_t;
|
||||
|
||||
typedef struct {
|
||||
connstate_t state; // connection status
|
||||
int keyCatchers; // bit flags
|
||||
|
||||
char servername[MAX_OSPATH]; // name of server from original connect (used by reconnect)
|
||||
|
||||
// when the server clears the hunk, all of these must be restarted
|
||||
qboolean rendererStarted;
|
||||
qboolean soundStarted;
|
||||
qboolean soundRegistered;
|
||||
qboolean uiStarted;
|
||||
qboolean cgameStarted;
|
||||
#ifdef _IMMERSION
|
||||
qboolean forceStarted;
|
||||
#endif // _IMMERSION
|
||||
|
||||
int framecount;
|
||||
int frametime; // msec since last frame
|
||||
float frametimeFraction; // fraction of a msec since last frame
|
||||
|
||||
int realtime; // ignores pause
|
||||
float realtimeFraction; // fraction of a msec accumulated
|
||||
int realFrametime; // ignoring pause, so console always works
|
||||
|
||||
// update server info
|
||||
char updateInfoString[MAX_INFO_STRING];
|
||||
|
||||
// rendering info
|
||||
glconfig_t glconfig;
|
||||
qhandle_t charSetShader;
|
||||
qhandle_t whiteShader;
|
||||
// qhandle_t consoleShader;
|
||||
|
||||
#ifdef _XBOX
|
||||
short mainGamepad;
|
||||
#endif
|
||||
} clientStatic_t;
|
||||
|
||||
#ifdef _XBOX
|
||||
#define CON_TEXTSIZE 256
|
||||
#else
|
||||
#define CON_TEXTSIZE 32768
|
||||
#endif
|
||||
#define NUM_CON_TIMES 4
|
||||
|
||||
typedef struct {
|
||||
qboolean initialized;
|
||||
|
||||
short text[CON_TEXTSIZE];
|
||||
int current; // line where next message will be printed
|
||||
int x; // offset in current line for next print
|
||||
int display; // bottom of console displays this line
|
||||
|
||||
int linewidth; // characters across screen
|
||||
int totallines; // total lines in console scrollback
|
||||
|
||||
float xadjust; // for wide aspect screens
|
||||
float yadjust;
|
||||
|
||||
float displayFrac; // aproaches finalFrac at scr_conspeed
|
||||
float finalFrac; // 0.0 to 1.0 lines of console to display
|
||||
|
||||
int vislines; // in scanlines
|
||||
|
||||
int times[NUM_CON_TIMES]; // cls.realtime time the line was generated
|
||||
// for transparent notify lines
|
||||
vec4_t color;
|
||||
} console_t;
|
||||
|
||||
extern clientStatic_t cls;
|
||||
|
||||
//=============================================================================
|
||||
|
||||
extern refexport_t re; // interface to refresh .dll
|
||||
|
||||
|
||||
//
|
||||
// cvars
|
||||
//
|
||||
extern cvar_t *cl_nodelta;
|
||||
extern cvar_t *cl_debugMove;
|
||||
extern cvar_t *cl_noprint;
|
||||
extern cvar_t *cl_timegraph;
|
||||
extern cvar_t *cl_maxpackets;
|
||||
extern cvar_t *cl_packetdup;
|
||||
extern cvar_t *cl_shownet;
|
||||
extern cvar_t *cl_timeNudge;
|
||||
extern cvar_t *cl_showTimeDelta;
|
||||
|
||||
extern cvar_t *cl_yawspeed;
|
||||
extern cvar_t *cl_pitchspeed;
|
||||
extern cvar_t *cl_run;
|
||||
extern cvar_t *cl_anglespeedkey;
|
||||
|
||||
extern cvar_t *cl_sensitivity;
|
||||
#ifdef _XBOX
|
||||
extern cvar_t *cl_sensitivityY;
|
||||
#endif
|
||||
|
||||
extern cvar_t *cl_freelook;
|
||||
|
||||
//extern cvar_t *cl_mouseAccel;
|
||||
//extern cvar_t *cl_showMouseRate;
|
||||
|
||||
extern cvar_t *cl_ingameVideo;
|
||||
extern cvar_t *cl_VideoQuality;
|
||||
extern cvar_t *cl_VidFadeUp;
|
||||
extern cvar_t *cl_VidFadeDown;
|
||||
|
||||
extern cvar_t *m_pitch;
|
||||
extern cvar_t *m_yaw;
|
||||
extern cvar_t *m_forward;
|
||||
extern cvar_t *m_side;
|
||||
//extern cvar_t *m_filter;
|
||||
|
||||
extern cvar_t *cl_activeAction;
|
||||
|
||||
extern cvar_t *cl_thumbStickMode;
|
||||
|
||||
//=================================================
|
||||
|
||||
//
|
||||
// cl_main
|
||||
//
|
||||
|
||||
void CL_Init (void);
|
||||
|
||||
void CL_AddReliableCommand( const char *cmd );
|
||||
|
||||
void CL_Disconnect_f (void);
|
||||
void CL_GetChallengePacket (void);
|
||||
void CL_Vid_Restart_f( void );
|
||||
void CL_Snd_Restart_f (void);
|
||||
|
||||
void CL_NextDemo( void );
|
||||
|
||||
void CL_GetPing( int n, char *adrstr, int *pingtime );
|
||||
void CL_ClearPing( int n );
|
||||
int CL_GetPingQueueCount( void );
|
||||
|
||||
extern qboolean SG_GameAllowedToSaveHere(qboolean inCamera);
|
||||
extern void CG_CenterPrint(const char *str, int y);
|
||||
extern bool autosaveTrigger;
|
||||
static void checkAutoSave();
|
||||
|
||||
//
|
||||
// cl_input
|
||||
//
|
||||
typedef struct {
|
||||
int down[2]; // key nums holding it down
|
||||
unsigned downtime; // msec timestamp
|
||||
unsigned msec; // msec down this frame if both a down and up happened
|
||||
qboolean active; // current state
|
||||
qboolean wasPressed; // set when down, not cleared when up
|
||||
} kbutton_t;
|
||||
|
||||
extern kbutton_t in_mlook, in_klook;
|
||||
extern kbutton_t in_strafe;
|
||||
extern kbutton_t in_speed;
|
||||
|
||||
void CL_InitInput (void);
|
||||
void CL_SendCmd (void);
|
||||
void CL_ClearState (void);
|
||||
void CL_ReadPackets (void);
|
||||
void CL_UpdateHotSwap(void);
|
||||
bool CL_ExtendSelectTime(void);
|
||||
|
||||
void CL_WritePacket( void );
|
||||
void IN_CenterView (void);
|
||||
|
||||
float CL_KeyState (kbutton_t *key);
|
||||
const char *Key_KeynumToString( int keynum/*, qboolean bTranslate*/ ); //note: translate is only called for menu display not configs
|
||||
|
||||
//
|
||||
// cl_parse.c
|
||||
//
|
||||
void CL_SystemInfoChanged( void );
|
||||
void CL_ParseServerMessage( msg_t *msg );
|
||||
|
||||
//====================================================================
|
||||
|
||||
void VID_MenuInit( void );
|
||||
void VID_MenuDraw( void );
|
||||
const char *VID_MenuKey( int );
|
||||
void VID_Printf (int print_level, const char *fmt, ...);
|
||||
|
||||
|
||||
//
|
||||
// console
|
||||
//
|
||||
void Con_DrawCharacter (int cx, int line, int num);
|
||||
|
||||
void Con_CheckResize (void);
|
||||
void Con_Init (void);
|
||||
void Con_Clear_f (void);
|
||||
void Con_ToggleConsole_f (void);
|
||||
void Con_DrawNotify (void);
|
||||
void Con_ClearNotify (void);
|
||||
void Con_RunConsole (void);
|
||||
void Con_DrawConsole (void);
|
||||
void Con_PageUp( void );
|
||||
void Con_PageDown( void );
|
||||
void Con_Top( void );
|
||||
void Con_Bottom( void );
|
||||
void Con_Close( void );
|
||||
|
||||
|
||||
//
|
||||
// cl_scrn.c
|
||||
//
|
||||
void SCR_Init (void);
|
||||
void SCR_UpdateScreen (void);
|
||||
|
||||
void SCR_DebugGraph (float value, int color);
|
||||
|
||||
int SCR_GetBigStringWidth( const char *str ); // returns in virtual 640x480 coordinates
|
||||
|
||||
void SCR_FillRect( float x, float y, float width, float height,
|
||||
const float *color );
|
||||
void SCR_DrawPic( float x, float y, float width, float height, qhandle_t hShader );
|
||||
void SCR_DrawNamedPic( float x, float y, float width, float height, const char *picname );
|
||||
|
||||
void SCR_DrawBigString( int x, int y, const char *s, float alpha ); // draws a string with embedded color control characters with fade
|
||||
void SCR_DrawBigStringColor( int x, int y, const char *s, vec4_t color ); // ignores embedded color control characters
|
||||
void SCR_DrawSmallString( int x, int y, const char *s, float alpha ); // draws a string with embedded color control characters with fade
|
||||
void SCR_DrawSmallStringColor( int x, int y, const char *s, vec4_t color ); // ignores embedded color control characters
|
||||
void SCR_DrawBigChar( int x, int y, int ch );
|
||||
void SCR_DrawSmallChar( int x, int y, int ch );
|
||||
|
||||
#ifdef _XBOX
|
||||
void SCR_PrecacheScreenshot();
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// cl_cin.c
|
||||
//
|
||||
void CL_PlayCinematic_f( void );
|
||||
void CL_PlayInGameCinematic_f(void);
|
||||
qboolean CL_CheckPendingCinematic(void);
|
||||
qboolean CL_IsRunningInGameCinematic(void);
|
||||
qboolean CL_InGameCinematicOnStandBy(void);
|
||||
void SCR_DrawCinematic (void);
|
||||
void SCR_RunCinematic (void);
|
||||
void SCR_StopCinematic( qboolean bAllowRefusal = qfalse );
|
||||
|
||||
int CIN_PlayCinematic( const char *arg0, int xpos, int ypos, int width, int height, int bits, const char *psAudioFile /* = NULL */);
|
||||
e_status CIN_StopCinematic(int handle);
|
||||
e_status CIN_RunCinematic (int handle);
|
||||
void CIN_DrawCinematic (int handle);
|
||||
void CIN_SetExtents (int handle, int x, int y, int w, int h);
|
||||
void CIN_SetLooping (int handle, qboolean loop);
|
||||
void CIN_UploadCinematic(int handle);
|
||||
void CIN_CloseAllVideos(void);
|
||||
|
||||
#ifdef _XBOX
|
||||
void CIN_Init(void);
|
||||
bool CIN_PlayAllFrames( const char *arg, int x, int y, int w, int h, int systemBits, bool keyBreakAllowed );
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// cl_cgame.c
|
||||
//
|
||||
void CL_InitCGame( void );
|
||||
void CL_ShutdownCGame( void );
|
||||
qboolean CL_GameCommand( void );
|
||||
void CL_CGameRendering( stereoFrame_t stereo );
|
||||
void CL_SetCGameTime( void );
|
||||
void CL_FirstSnapshot( void );
|
||||
|
||||
|
||||
//
|
||||
// cl_ui.c
|
||||
//
|
||||
void CL_InitUI( void );
|
||||
void CL_ShutdownUI( void );
|
||||
void CL_GenericMenu_f(void);
|
||||
void CL_DataPad_f(void);
|
||||
void CL_EndScreenDissolve_f(void);
|
||||
|
||||
#endif //__CLIENT_H__
|
||||
13
code/client/client_ui.h
Normal file
13
code/client/client_ui.h
Normal file
@@ -0,0 +1,13 @@
|
||||
// client_ui.h -- header for client access to ui funcs
|
||||
#ifndef __CLIENTUI_H__
|
||||
#define __CLIENTUI_H__
|
||||
|
||||
#include "../ui/ui_public.h"
|
||||
|
||||
void _UI_KeyEvent( int key, qboolean down );
|
||||
void UI_SetActiveMenu( const char* menuname,const char *menuID );
|
||||
void UI_UpdateConnectionMessageString( char *string );
|
||||
qboolean UI_ConsoleCommand( void ) ;
|
||||
qboolean _UI_IsFullscreen( void );
|
||||
|
||||
#endif //__CLIENTUI_H__
|
||||
171
code/client/eax/EaxMan.h
Normal file
171
code/client/eax/EaxMan.h
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
*/
|
||||
#ifndef __EAXMANH
|
||||
#define __EAXMANH
|
||||
|
||||
#define COM_NO_WINDOWS_H
|
||||
#include <objbase.h>
|
||||
#include "eax.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
//#define CLSID_EAXMANAGER CLSID_EAX20_Manager
|
||||
//#define IID_IEaxManager IID_EAX20_Manager
|
||||
#define EM_MAX_NAME 32
|
||||
|
||||
#define EMFLAG_IDDEFAULT (-1)
|
||||
#define EMFLAG_IDNONE (-2)
|
||||
#define EMFLAG_LOCKPOSITION 1
|
||||
#define EMFLAG_LOADFROMMEMORY 2
|
||||
#define EMFLAG_NODIFFRACTION 4
|
||||
|
||||
typedef struct _EMPOINT {
|
||||
float fX;
|
||||
float fY;
|
||||
float fZ;
|
||||
} EMPOINT;
|
||||
typedef EMPOINT FAR *LPEMPOINT;
|
||||
|
||||
typedef struct _LISTENERATTRIBUTES {
|
||||
float fDistanceFactor;
|
||||
float fRolloffFactor;
|
||||
float fDopplerFactor;
|
||||
} LISTENERATTRIBUTES;
|
||||
typedef LISTENERATTRIBUTES FAR *LPLISTENERATTRIBUTES;
|
||||
|
||||
typedef struct _SOURCEATTRIBUTES {
|
||||
EAXSOURCEPROPERTIES eaxAttributes;
|
||||
unsigned long ulInsideConeAngle;
|
||||
unsigned long ulOutsideConeAngle;
|
||||
long lConeOutsideVolume;
|
||||
float fConeXdir;
|
||||
float fConeYdir;
|
||||
float fConeZdir;
|
||||
float fMinDistance;
|
||||
float fMaxDistance;
|
||||
long lDupCount;
|
||||
long lPriority;
|
||||
} SOURCEATTRIBUTES;
|
||||
typedef SOURCEATTRIBUTES FAR *LPSOURCEATTRIBUTES;
|
||||
|
||||
typedef struct _MATERIALATTRIBUTES {
|
||||
long lLevel;
|
||||
float fLFRatio;
|
||||
float fRoomRatio;
|
||||
DWORD dwFlags;
|
||||
} MATERIALATTRIBUTES;
|
||||
typedef MATERIALATTRIBUTES FAR *LPMATERIALATTRIBUTES;
|
||||
|
||||
#define EMMATERIAL_OBSTRUCTS 1
|
||||
#define EMMATERIAL_OCCLUDES 3
|
||||
|
||||
typedef struct _DIFFRACTIONBOX {
|
||||
long lSubspaceID;
|
||||
EMPOINT empMin;
|
||||
EMPOINT empMax;
|
||||
} DIFFRACTIONBOX;
|
||||
typedef DIFFRACTIONBOX FAR *LPDIFFRACTIONBOX;
|
||||
|
||||
// {7CE4D6E6-562F-11d3-8812-005004062F83}
|
||||
DEFINE_GUID(CLSID_EAXMANAGER, 0x60b721a1, 0xf7c8, 0x11d2, 0xa0, 0x2e, 0x0, 0x50, 0x4, 0x6, 0x18, 0xb8);
|
||||
|
||||
#ifdef __cplusplus
|
||||
struct IEaxManager;
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef struct IEaxManager *LPEAXMANAGER;
|
||||
|
||||
// {7CE4D6E8-562F-11d3-8812-005004062F83}
|
||||
DEFINE_GUID(IID_IEaxManager, 0x60b721a2, 0xf7c8, 0x11d2, 0xa0, 0x2e, 0x0, 0x50, 0x4, 0x6, 0x18, 0xb8);
|
||||
|
||||
#undef INTERFACE
|
||||
#define INTERFACE IEaxManager
|
||||
|
||||
extern HRESULT __stdcall EaxManagerCreate(LPEAXMANAGER*);
|
||||
typedef HRESULT (__stdcall *LPEAXMANAGERCREATE)(LPEAXMANAGER*);
|
||||
|
||||
DECLARE_INTERFACE_(IEaxManager, IUnknown)
|
||||
{
|
||||
// IUnknown methods
|
||||
STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE;
|
||||
STDMETHOD_(ULONG,AddRef) (THIS) PURE;
|
||||
STDMETHOD_(ULONG,Release) (THIS) PURE;
|
||||
|
||||
STDMETHOD(GetDataSetSize) (THIS_ unsigned long*, DWORD) PURE;
|
||||
STDMETHOD(LoadDataSet) (THIS_ char*, DWORD) PURE;
|
||||
STDMETHOD(FreeDataSet) (THIS_ DWORD) PURE;
|
||||
STDMETHOD(GetListenerAttributes) (THIS_ LPLISTENERATTRIBUTES) PURE;
|
||||
STDMETHOD(GetSourceID) (THIS_ char*, long*) PURE;
|
||||
STDMETHOD(GetSourceAttributes) (THIS_ long, LPSOURCEATTRIBUTES) PURE;
|
||||
STDMETHOD(GetSourceNumInstances) (THIS_ long, long*) PURE;
|
||||
STDMETHOD(GetSourceInstancePos) (THIS_ long, long, LPEMPOINT) PURE;
|
||||
STDMETHOD(GetEnvironmentID) (THIS_ char*, long*) PURE;
|
||||
STDMETHOD(GetEnvironmentAttributes) (THIS_ long, LPEAXREVERBPROPERTIES) PURE;
|
||||
STDMETHOD(GetMaterialID) (THIS_ char*, long*) PURE;
|
||||
STDMETHOD(GetMaterialAttributes) (THIS_ long, LPMATERIALATTRIBUTES) PURE;
|
||||
STDMETHOD(GetGeometrySetID) (THIS_ char*, long*) PURE;
|
||||
STDMETHOD(GetListenerDynamicAttributes) (THIS_ long, LPEMPOINT, long*, DWORD) PURE;
|
||||
STDMETHOD(GetSourceDynamicAttributes) (THIS_ long, LPEMPOINT, long*, float*, long*, float*, float*, LPEMPOINT, DWORD) PURE;
|
||||
// STDMETHOD(GetSubSpaceID) (THIS_ long, LPEMPOINT, long *) PURE;
|
||||
STDMETHOD(GetEnvironmentName) (THIS_ long, char *szString, long lStrlen) PURE;
|
||||
};
|
||||
|
||||
#if !defined(__cplusplus) || defined(CINTERFACE)
|
||||
#define IEaxManager_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
|
||||
#define IEaxManager_AddRef(p) (p)->lpVtbl->AddRef(p)
|
||||
#define IEaxManager_Release(p) (p)->lpVtbl->Release(p)
|
||||
#define IEaxManager_GetDataSetSize(p,a,b) (p)->lpVtbl->GetDataSetSize(p,a,b)
|
||||
#define IEaxManager_LoadDataSet(p,a,b) (p)->lpVtbl->LoadDataSet(p,a,b)
|
||||
#define IEaxManager_FreeDataSet(p,a) (p)->lpVtbl->FreeDataSet(p,a)
|
||||
#define IEaxManager_GetListenerAttributes(p,a) (p)->lpVtbl->GetListenerAttributes(p,a)
|
||||
#define IEaxManager_GetSourceID(p,a,b) (p)->lpVtbl->GetSourceID(p,a,b)
|
||||
#define IEaxManager_GetSourceAttributes(p,a,b) (p)->lpVtbl->GetSourceAttributes(p,a,b)
|
||||
#define IEaxManager_GetSourceNumInstances(p,a,b) (p)->lpVtbl->GetSourceNumInstances(p,a,b)
|
||||
#define IEaxManager_GetSourceInstancePos(p,a,b,c) (p)->lpVtbl->GetSourceInstancePos(p,a,b,c)
|
||||
#define IEaxManager_GetEnvironmentID(p,a,b) (p)->lpVtbl->GetEnvironmentID(p,a,b)
|
||||
#define IEaxManager_GetEnvironmentAttributes(p,a,b) (p)->lpVtbl->GetEnvironmentAttributes(p,a,b)
|
||||
#define IEaxManager_GetMaterialID(p,a,b) (p)->lpVtbl->GetMaterialID(p,a,b)
|
||||
#define IEaxManager_GetMaterialAttributes(p,a,b) (p)->lpVtbl->GetMaterialAttributes(p,a,b)
|
||||
#define IEaxManager_GetGeometrySetID(p,a,b) (p)->lpVtbl->GetGeometrySetID(p,a,b)
|
||||
#define IEaxManager_GetListenerDynamicAttributes(p,a,b,c,d) (p)->lpVtbl->GetListenerDynamicAttributes(p,a,b,c,d)
|
||||
#define IEaxManager_GetSourceDynamicAttributes(p,a,b,c,d,e,f,g,h,i) (p)->lpVtbl->GetSourceDynamicAttributes(p,a,b,c,d,e,f,g,h,i)
|
||||
//#define IEaxManager_GetSubSpaceID(p,a,b,c) (p)->lpVtbl->GetSubSpaceID(p,a,b,c)
|
||||
#define IEaxManager_GetEnvironmentName(p,a,b,c) (p)->lpVtbl->GetEnvironmentName(p,a,b,c)
|
||||
#else
|
||||
#define IEaxManager_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
|
||||
#define IEaxManager_AddRef(p) (p)->AddRef()
|
||||
#define IEaxManager_Release(p) (p)->Release()
|
||||
#define IEaxManager_GetDataSetSize(p,a,b) (p)->GetDataSetSize(a,b)
|
||||
#define IEaxManager_LoadDataSet(p,a,b) (p)->LoadDataSet(a,b)
|
||||
#define IEaxManager_FreeDataSet(p,a) (p)->FreeDataSet(a)
|
||||
#define IEaxManager_GetListenerAttributes(p,a) (p)->GetListenerAttributes(a)
|
||||
#define IEaxManager_GetSourceID(p,a,b) (p)->GetSourceID(a,b)
|
||||
#define IEaxManager_GetSourceAttributes(p,a,b) (p)->GetSourceAttributes(a,b)
|
||||
#define IEaxManager_GetSourceNumInstances(p,a,b) (p)->GetSourceNumInstances(a,b)
|
||||
#define IEaxManager_GetSourceInstancePos(p,a,b,c) (p)->GetSourceInstancePos(a,b,c)
|
||||
#define IEaxManager_GetEnvironmentID(p,a,b) (p)->GetEnvironmentID(a,b)
|
||||
#define IEaxManager_GetEnvironmentAttributes(p,a,b) (p)->GetEnvironmentAttributes(a,b)
|
||||
#define IEaxManager_GetMaterialID(p,a,b) (p)->GetMaterialID(a,b)
|
||||
#define IEaxManager_GetMaterialAttributes(p,a,b) (p)->GetMaterialAttributes(a,b)
|
||||
#define IEaxManager_GetGeometrySetID(p,a,b) (p)->GetGeometrySetID(a,b)
|
||||
#define IEaxManager_GetListenerDynamicAttributes(p,a,b,c,d) (p)->GetListenerDynamicAttributes(a,b,c,d)
|
||||
#define IEaxManager_GetSourceDynamicAttributes(p,a,b,c,d,e,f,g,h,i) (p)->GetSourceDynamicAttributes(a,b,c,d,e,f,g,h,i)
|
||||
//#define IEaxManager_GetSubSpaceID(p,a,b,c) (p)->GetSubSpaceID(a,b,c)
|
||||
#define IEaxManager_GetEnvironmentName(p,a,b,c) (p)->GetEnvironmentName(a,b,c)
|
||||
#endif
|
||||
|
||||
#define EM_OK 0
|
||||
#define EM_INVALIDID MAKE_HRESULT(1, FACILITY_ITF, 1)
|
||||
#define EM_IDNOTFOUND MAKE_HRESULT(1, FACILITY_ITF, 2)
|
||||
#define EM_FILENOTFOUND MAKE_HRESULT(1, FACILITY_ITF, 3)
|
||||
#define EM_FILEINVALID MAKE_HRESULT(1, FACILITY_ITF, 4)
|
||||
#define EM_VERSIONINVALID MAKE_HRESULT(1, FACILITY_ITF, 5)
|
||||
#define EM_INSTANCENOTFOUND MAKE_HRESULT(1, FACILITY_ITF, 6)
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
1562
code/client/eax/eax.h
Normal file
1562
code/client/eax/eax.h
Normal file
File diff suppressed because it is too large
Load Diff
129
code/client/fffx.h
Normal file
129
code/client/fffx.h
Normal file
@@ -0,0 +1,129 @@
|
||||
// Filename:- fffx.h (Force Feedback FX)
|
||||
|
||||
#ifndef FFFX_H
|
||||
#define FFFX_H
|
||||
|
||||
// this part can be seen by the CGAME as well...
|
||||
|
||||
// These enums match the generic ones built into the effects ROM in the MS SideWinder FF Joystick,
|
||||
// so blame MS for anything you don't like (like that aircraft carrier one - jeez!)...
|
||||
//
|
||||
// (Judging from the names of most of these, the MS FF guys appear to be rather fond of ID-type games...)
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
fffx_RandomNoise=0,
|
||||
fffx_AircraftCarrierTakeOff, // this one is pointless / dumb
|
||||
fffx_BasketballDribble,
|
||||
fffx_CarEngineIdle,
|
||||
fffx_ChainsawIdle,
|
||||
fffx_ChainsawInAction,
|
||||
fffx_DieselEngineIdle,
|
||||
fffx_Jump,
|
||||
fffx_Land,
|
||||
fffx_MachineGun,
|
||||
fffx_Punched,
|
||||
fffx_RocketLaunch,
|
||||
fffx_SecretDoor,
|
||||
fffx_SwitchClick,
|
||||
fffx_WindGust,
|
||||
fffx_WindShear, // also pretty crap
|
||||
fffx_Pistol,
|
||||
fffx_Shotgun,
|
||||
fffx_Laser1,
|
||||
fffx_Laser2,
|
||||
fffx_Laser3,
|
||||
fffx_Laser4,
|
||||
fffx_Laser5,
|
||||
fffx_Laser6,
|
||||
fffx_OutOfAmmo,
|
||||
fffx_LightningGun,
|
||||
fffx_Missile,
|
||||
fffx_GatlingGun,
|
||||
fffx_ShortPlasma,
|
||||
fffx_PlasmaCannon1,
|
||||
fffx_PlasmaCannon2,
|
||||
fffx_Cannon,
|
||||
#ifdef _XBOX
|
||||
fffx_FallingShort,
|
||||
fffx_FallingMedium,
|
||||
fffx_FallingFar,
|
||||
fffx_StartConst,
|
||||
fffx_StopConst,
|
||||
#endif
|
||||
//
|
||||
fffx_NUMBEROF,
|
||||
fffx_NULL // special use, ignore during array mallocs etc, use fffx_NUMBEROF instead
|
||||
} ffFX_e;
|
||||
|
||||
|
||||
#ifndef CGAME_ONLY
|
||||
|
||||
/////////////////////////// START of functions to call /////////////////////////////////
|
||||
//
|
||||
//
|
||||
//
|
||||
// Once the game is running you should *only* access FF functions through these 4 macros. Savvy?
|
||||
//
|
||||
// Usage note: In practice, you can have about 4 FF FX running concurrently, though I defy anyone to make sense
|
||||
// of that amount of white-noise vibration. MS guidelines say you shouldn't leave vibration on for long periods
|
||||
// of time (eg engine rumble) because of various nerve-damage/lawsuit issues, so for this reason there is no API
|
||||
// support for setting durations etc. All FF FX stuff here is designed for things like firing, hit damage, driving
|
||||
// over bumps, etc that can be played as one-off events, though you *can* do things like FFFX_ENSURE(fffx_ChainsawIdle)
|
||||
// if you really want to.
|
||||
//
|
||||
// Combining small numbers of effects such as having a laser firing (MS photons have higher mass apparently <g>),
|
||||
// and then firing a machine gun in bursts as well are no problem, and easily felt, hence the ability to stop playing
|
||||
// individual FF FX.
|
||||
//
|
||||
#define FFFX_START(f) FF_Play(f)
|
||||
#define FFFX_ENSURE(f) FF_EnsurePlaying(f)
|
||||
#define FFFX_STOP(f) FF_Stop(f) // some effects (eg. gatling, chainsaw), need this, or they play too long after trigger-off.
|
||||
#define FFFX_STOPALL FF_StopAll()
|
||||
|
||||
|
||||
//
|
||||
// These 2 are called at app start/stop, but you can call FF_Init to change FF devices anytime (takes a couple of seconds)
|
||||
//
|
||||
void FF_Init(qboolean bTryMouseFirst=true);
|
||||
void FF_Shutdown(void);
|
||||
//
|
||||
// other stuff you may want to call but don't have to...
|
||||
//
|
||||
qboolean FF_IsAvailable(void);
|
||||
qboolean FF_IsMouse(void);
|
||||
qboolean FF_SetTension(int iTension); // tension setting 0..3 (0=none)
|
||||
qboolean FF_SetSpring(long lSpring); // precision version of above, 0..n..10000
|
||||
// (only provided for command line fiddling with
|
||||
// weird hardware. FF_SetTension(1) = default
|
||||
// = FF_SetSpring(2000) (internal lookup table))
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
/////////////////////////// END of functions to call /////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
// do *not* call this functions directly (or else!), use the macros above
|
||||
//
|
||||
void FF_Play (ffFX_e fffx);
|
||||
void FF_EnsurePlaying (ffFX_e fffx);
|
||||
void FF_Stop (ffFX_e fffx);
|
||||
void FF_StopAll (void);
|
||||
|
||||
#ifdef _XBOX
|
||||
void FF_XboxShake (float intensity, int duration);
|
||||
void FF_XboxDamage (int damage, float xpos);
|
||||
#endif
|
||||
|
||||
#define MAX_CONCURRENT_FFFXs 4 // only for my code to use/read, do NOT alter!
|
||||
|
||||
|
||||
|
||||
#endif // #ifndef CGAME_ONLY
|
||||
#endif // #ifndef FFFX_H
|
||||
|
||||
//////////////////////// eof //////////////////////
|
||||
|
||||
347
code/client/keycodes.h
Normal file
347
code/client/keycodes.h
Normal file
@@ -0,0 +1,347 @@
|
||||
#ifndef __KEYCODES_H__
|
||||
#define __KEYCODES_H__
|
||||
|
||||
// these are the key numbers that should be passed to KeyEvent
|
||||
|
||||
typedef enum
|
||||
{
|
||||
A_NULL = 0,
|
||||
A_SHIFT,
|
||||
A_CTRL,
|
||||
A_ALT,
|
||||
A_CAPSLOCK,
|
||||
A_NUMLOCK,
|
||||
A_SCROLLLOCK,
|
||||
A_PAUSE,
|
||||
A_BACKSPACE,
|
||||
A_TAB,
|
||||
A_ENTER,
|
||||
A_KP_PLUS,
|
||||
A_KP_MINUS,
|
||||
A_KP_ENTER,
|
||||
A_KP_PERIOD,
|
||||
A_PRINTSCREEN,
|
||||
A_KP_0,
|
||||
A_KP_1,
|
||||
A_KP_2,
|
||||
A_KP_3,
|
||||
A_KP_4,
|
||||
A_KP_5,
|
||||
A_KP_6,
|
||||
A_KP_7,
|
||||
A_KP_8,
|
||||
A_KP_9,
|
||||
A_CONSOLE,
|
||||
A_ESCAPE,
|
||||
A_F1,
|
||||
A_F2,
|
||||
A_F3,
|
||||
A_F4,
|
||||
|
||||
A_SPACE,
|
||||
A_PLING,
|
||||
A_DOUBLE_QUOTE,
|
||||
A_HASH,
|
||||
A_STRING,
|
||||
A_PERCENT,
|
||||
A_AND,
|
||||
A_SINGLE_QUOTE,
|
||||
A_OPEN_BRACKET,
|
||||
A_CLOSE_BRACKET,
|
||||
A_STAR,
|
||||
A_PLUS,
|
||||
A_COMMA,
|
||||
A_MINUS,
|
||||
A_PERIOD,
|
||||
A_FORWARD_SLASH,
|
||||
A_0,
|
||||
A_1,
|
||||
A_2,
|
||||
A_3,
|
||||
A_4,
|
||||
A_5,
|
||||
A_6,
|
||||
A_7,
|
||||
A_8,
|
||||
A_9,
|
||||
A_COLON,
|
||||
A_SEMICOLON,
|
||||
A_LESSTHAN,
|
||||
A_EQUALS,
|
||||
A_GREATERTHAN,
|
||||
A_QUESTION,
|
||||
|
||||
A_AT,
|
||||
A_CAP_A,
|
||||
A_CAP_B,
|
||||
A_CAP_C,
|
||||
A_CAP_D,
|
||||
A_CAP_E,
|
||||
A_CAP_F,
|
||||
A_CAP_G,
|
||||
A_CAP_H,
|
||||
A_CAP_I,
|
||||
A_CAP_J,
|
||||
A_CAP_K,
|
||||
A_CAP_L,
|
||||
A_CAP_M,
|
||||
A_CAP_N,
|
||||
A_CAP_O,
|
||||
A_CAP_P,
|
||||
A_CAP_Q,
|
||||
A_CAP_R,
|
||||
A_CAP_S,
|
||||
A_CAP_T,
|
||||
A_CAP_U,
|
||||
A_CAP_V,
|
||||
A_CAP_W,
|
||||
A_CAP_X,
|
||||
A_CAP_Y,
|
||||
A_CAP_Z,
|
||||
A_OPEN_SQUARE,
|
||||
A_BACKSLASH,
|
||||
A_CLOSE_SQUARE,
|
||||
A_CARET,
|
||||
A_UNDERSCORE,
|
||||
|
||||
A_LEFT_SINGLE_QUOTE,
|
||||
A_LOW_A,
|
||||
A_LOW_B,
|
||||
A_LOW_C,
|
||||
A_LOW_D,
|
||||
A_LOW_E,
|
||||
A_LOW_F,
|
||||
A_LOW_G,
|
||||
A_LOW_H,
|
||||
A_LOW_I,
|
||||
A_LOW_J,
|
||||
A_LOW_K,
|
||||
A_LOW_L,
|
||||
A_LOW_M,
|
||||
A_LOW_N,
|
||||
A_LOW_O,
|
||||
A_LOW_P,
|
||||
A_LOW_Q,
|
||||
A_LOW_R,
|
||||
A_LOW_S,
|
||||
A_LOW_T,
|
||||
A_LOW_U,
|
||||
A_LOW_V,
|
||||
A_LOW_W,
|
||||
A_LOW_X,
|
||||
A_LOW_Y,
|
||||
A_LOW_Z,
|
||||
A_OPEN_BRACE,
|
||||
A_BAR,
|
||||
A_CLOSE_BRACE,
|
||||
A_TILDE,
|
||||
A_DELETE,
|
||||
|
||||
A_EURO,
|
||||
A_SHIFT2,
|
||||
A_CTRL2,
|
||||
A_ALT2,
|
||||
A_F5,
|
||||
A_F6,
|
||||
A_F7,
|
||||
A_F8,
|
||||
A_CIRCUMFLEX,
|
||||
A_MWHEELUP,
|
||||
A_CAP_SCARON,
|
||||
A_MWHEELDOWN,
|
||||
A_CAP_OE,
|
||||
A_MOUSE1,
|
||||
A_MOUSE2,
|
||||
A_INSERT,
|
||||
A_HOME,
|
||||
A_PAGE_UP,
|
||||
A_RIGHT_SINGLE_QUOTE,
|
||||
A_LEFT_DOUBLE_QUOTE,
|
||||
A_RIGHT_DOUBLE_QUOTE,
|
||||
A_F9,
|
||||
A_F10,
|
||||
A_F11,
|
||||
A_F12,
|
||||
A_TRADEMARK,
|
||||
A_LOW_SCARON,
|
||||
A_SHIFT_ENTER,
|
||||
A_LOW_OE,
|
||||
A_END,
|
||||
A_PAGE_DOWN,
|
||||
A_CAP_YDIERESIS,
|
||||
|
||||
A_SHIFT_SPACE,
|
||||
A_EXCLAMDOWN,
|
||||
A_CENT,
|
||||
A_POUND,
|
||||
A_SHIFT_KP_ENTER,
|
||||
A_YEN,
|
||||
A_MOUSE3,
|
||||
A_MOUSE4,
|
||||
A_MOUSE5,
|
||||
A_COPYRIGHT,
|
||||
A_CURSOR_UP,
|
||||
A_CURSOR_DOWN,
|
||||
A_CURSOR_LEFT,
|
||||
A_CURSOR_RIGHT,
|
||||
A_REGISTERED,
|
||||
A_UNDEFINED_7,
|
||||
A_UNDEFINED_8,
|
||||
A_UNDEFINED_9,
|
||||
A_UNDEFINED_10,
|
||||
A_UNDEFINED_11,
|
||||
A_UNDEFINED_12,
|
||||
A_UNDEFINED_13,
|
||||
A_UNDEFINED_14,
|
||||
A_UNDEFINED_15,
|
||||
A_UNDEFINED_16,
|
||||
A_UNDEFINED_17,
|
||||
A_UNDEFINED_18,
|
||||
A_UNDEFINED_19,
|
||||
A_UNDEFINED_20,
|
||||
A_UNDEFINED_21,
|
||||
A_UNDEFINED_22,
|
||||
A_QUESTION_DOWN,
|
||||
|
||||
A_CAP_AGRAVE,
|
||||
A_CAP_AACUTE,
|
||||
A_CAP_ACIRCUMFLEX,
|
||||
A_CAP_ATILDE,
|
||||
A_CAP_ADIERESIS,
|
||||
A_CAP_ARING,
|
||||
A_CAP_AE,
|
||||
A_CAP_CCEDILLA,
|
||||
A_CAP_EGRAVE,
|
||||
A_CAP_EACUTE,
|
||||
A_CAP_ECIRCUMFLEX,
|
||||
A_CAP_EDIERESIS,
|
||||
A_CAP_IGRAVE,
|
||||
A_CAP_IACUTE,
|
||||
A_CAP_ICIRCUMFLEX,
|
||||
A_CAP_IDIERESIS,
|
||||
A_CAP_ETH,
|
||||
A_CAP_NTILDE,
|
||||
A_CAP_OGRAVE,
|
||||
A_CAP_OACUTE,
|
||||
A_CAP_OCIRCUMFLEX,
|
||||
A_CAP_OTILDE,
|
||||
A_CAP_ODIERESIS,
|
||||
A_MULTIPLY,
|
||||
A_CAP_OSLASH,
|
||||
A_CAP_UGRAVE,
|
||||
A_CAP_UACUTE,
|
||||
A_CAP_UCIRCUMFLEX,
|
||||
A_CAP_UDIERESIS,
|
||||
A_CAP_YACUTE,
|
||||
A_CAP_THORN,
|
||||
A_GERMANDBLS,
|
||||
|
||||
A_LOW_AGRAVE,
|
||||
A_LOW_AACUTE,
|
||||
A_LOW_ACIRCUMFLEX,
|
||||
A_LOW_ATILDE,
|
||||
A_LOW_ADIERESIS,
|
||||
A_LOW_ARING,
|
||||
A_LOW_AE,
|
||||
A_LOW_CCEDILLA,
|
||||
A_LOW_EGRAVE,
|
||||
A_LOW_EACUTE,
|
||||
A_LOW_ECIRCUMFLEX,
|
||||
A_LOW_EDIERESIS,
|
||||
A_LOW_IGRAVE,
|
||||
A_LOW_IACUTE,
|
||||
A_LOW_ICIRCUMFLEX,
|
||||
A_LOW_IDIERESIS,
|
||||
A_LOW_ETH,
|
||||
A_LOW_NTILDE,
|
||||
A_LOW_OGRAVE,
|
||||
A_LOW_OACUTE,
|
||||
A_LOW_OCIRCUMFLEX,
|
||||
A_LOW_OTILDE,
|
||||
A_LOW_ODIERESIS,
|
||||
A_DIVIDE,
|
||||
A_LOW_OSLASH,
|
||||
A_LOW_UGRAVE,
|
||||
A_LOW_UACUTE,
|
||||
A_LOW_UCIRCUMFLEX,
|
||||
A_LOW_UDIERESIS,
|
||||
A_LOW_YACUTE,
|
||||
A_LOW_THORN,
|
||||
A_LOW_YDIERESIS,
|
||||
|
||||
A_JOY0,
|
||||
A_JOY1,
|
||||
A_JOY2,
|
||||
A_JOY3,
|
||||
A_JOY4,
|
||||
A_JOY5,
|
||||
A_JOY6,
|
||||
A_JOY7,
|
||||
A_JOY8,
|
||||
A_JOY9,
|
||||
A_JOY10,
|
||||
A_JOY11,
|
||||
A_JOY12,
|
||||
A_JOY13,
|
||||
A_JOY14,
|
||||
A_JOY15,
|
||||
A_JOY16,
|
||||
A_JOY17,
|
||||
A_JOY18,
|
||||
A_JOY19,
|
||||
A_JOY20,
|
||||
A_JOY21,
|
||||
A_JOY22,
|
||||
A_JOY23,
|
||||
A_JOY24,
|
||||
A_JOY25,
|
||||
A_JOY26,
|
||||
A_JOY27,
|
||||
A_JOY28,
|
||||
A_JOY29,
|
||||
A_JOY30,
|
||||
A_JOY31,
|
||||
|
||||
A_AUX0,
|
||||
A_AUX1,
|
||||
A_AUX2,
|
||||
A_AUX3,
|
||||
A_AUX4,
|
||||
A_AUX5,
|
||||
A_AUX6,
|
||||
A_AUX7,
|
||||
A_AUX8,
|
||||
A_AUX9,
|
||||
A_AUX10,
|
||||
A_AUX11,
|
||||
A_AUX12,
|
||||
A_AUX13,
|
||||
A_AUX14,
|
||||
A_AUX15,
|
||||
A_AUX16,
|
||||
A_AUX17,
|
||||
A_AUX18,
|
||||
A_AUX19,
|
||||
A_AUX20,
|
||||
A_AUX21,
|
||||
A_AUX22,
|
||||
A_AUX23,
|
||||
A_AUX24,
|
||||
A_AUX25,
|
||||
A_AUX26,
|
||||
A_AUX27,
|
||||
A_AUX28,
|
||||
A_AUX29,
|
||||
A_AUX30,
|
||||
A_AUX31,
|
||||
|
||||
MAX_KEYS
|
||||
} fakeAscii_t;
|
||||
|
||||
|
||||
// The menu code needs to get both key and char events, but
|
||||
// to avoid duplicating the paths, the char events are just
|
||||
// distinguished by or'ing in K_CHAR_FLAG (ugly)
|
||||
#define K_CHAR_FLAG 1024
|
||||
|
||||
#endif
|
||||
61
code/client/keys.h
Normal file
61
code/client/keys.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "keycodes.h"
|
||||
|
||||
typedef struct {
|
||||
qboolean down;
|
||||
int repeats; // if > 1, it is autorepeating
|
||||
char *binding;
|
||||
} qkey_t;
|
||||
|
||||
#define MAX_EDIT_LINE 256
|
||||
#define COMMAND_HISTORY 32
|
||||
|
||||
typedef struct {
|
||||
int cursor;
|
||||
int scroll;
|
||||
int widthInChars;
|
||||
char buffer[MAX_EDIT_LINE];
|
||||
} field_t;
|
||||
|
||||
typedef struct keyGlobals_s
|
||||
{
|
||||
field_t historyEditLines[COMMAND_HISTORY];
|
||||
|
||||
int nextHistoryLine; // the last line in the history buffer, not masked
|
||||
int historyLine; // the line being displayed from history buffer
|
||||
// will be <= nextHistoryLine
|
||||
field_t g_consoleField;
|
||||
|
||||
qboolean anykeydown;
|
||||
qboolean key_overstrikeMode;
|
||||
int keyDownCount;
|
||||
|
||||
qkey_t keys[MAX_KEYS];
|
||||
} keyGlobals_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
word upper;
|
||||
word lower;
|
||||
char *name;
|
||||
int keynum;
|
||||
bool menukey;
|
||||
} keyname_t;
|
||||
|
||||
extern keyGlobals_t kg;
|
||||
extern keyname_t keynames[MAX_KEYS];
|
||||
|
||||
void Field_Clear( field_t *edit );
|
||||
void Field_KeyDownEvent( field_t *edit, int key );
|
||||
void Field_Draw( field_t *edit, int x, int y, int width, qboolean showCursor );
|
||||
void Field_BigDraw( field_t *edit, int x, int y, int width, qboolean showCursor );
|
||||
|
||||
extern field_t chatField;
|
||||
|
||||
void Key_WriteBindings( fileHandle_t f );
|
||||
void Key_SetBinding( int keynum, const char *binding );
|
||||
char *Key_GetBinding( int keynum );
|
||||
qboolean Key_IsDown( int keynum );
|
||||
qboolean Key_GetOverstrikeMode( void );
|
||||
void Key_SetOverstrikeMode( qboolean state );
|
||||
void Key_ClearStates( void );
|
||||
1165
code/client/snd_ambient.cpp
Normal file
1165
code/client/snd_ambient.cpp
Normal file
File diff suppressed because it is too large
Load Diff
118
code/client/snd_ambient.h
Normal file
118
code/client/snd_ambient.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#ifndef __SND_AMBIENT__
|
||||
#define __SND_AMBIENT__
|
||||
|
||||
// Includes
|
||||
|
||||
#pragma warning ( disable : 4786 )
|
||||
#pragma warning ( disable : 4511 ) //copy constructor could not be gen
|
||||
#pragma warning ( disable : 4512 ) //assign constructor could not be gen
|
||||
|
||||
//these don't work because stl re-sets them
|
||||
//#pragma warning ( disable : 4663 ) //spcialize class
|
||||
//#pragma warning ( disable : 4018 ) //signed/unsigned
|
||||
#pragma warning (disable:4503) // decorated name length xceeded, name was truncated
|
||||
#pragma warning (push, 3) //go back down to 3 for the stl include
|
||||
|
||||
#include "../qcommon/sstring.h" // #include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#pragma warning (pop)
|
||||
#pragma warning (disable:4503) // decorated name length xceeded, name was truncated
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Defines
|
||||
|
||||
#define AMBIENT_SET_FILENAME "sound/sound.txt"
|
||||
|
||||
const int MAX_WAVES_PER_GROUP = 8;
|
||||
const int MAX_SET_NAME_LENGTH = 64;
|
||||
|
||||
// Enums
|
||||
|
||||
enum set_e
|
||||
{
|
||||
AS_SET_GENERAL, //General sets
|
||||
AS_SET_LOCAL, //Local sets (regional)
|
||||
AS_SET_BMODEL, //Brush model sets (doors, plats, etc.)
|
||||
|
||||
NUM_AS_SETS
|
||||
};
|
||||
|
||||
enum setKeyword_e
|
||||
{
|
||||
SET_KEYWORD_TIMEBETWEENWAVES,
|
||||
SET_KEYWORD_SUBWAVES,
|
||||
SET_KEYWORD_LOOPEDWAVE,
|
||||
SET_KEYWORD_VOLRANGE,
|
||||
SET_KEYWORD_RADIUS,
|
||||
SET_KEYWORD_TYPE,
|
||||
SET_KEYWORD_AMSDIR,
|
||||
SET_KEYWORD_OUTDIR,
|
||||
SET_KEYWORD_BASEDIR,
|
||||
|
||||
NUM_AS_KEYWORDS,
|
||||
};
|
||||
|
||||
// Structures
|
||||
|
||||
//NOTENOTE: Was going to make this a class, but don't want to muck around
|
||||
typedef struct ambientSet_s
|
||||
{
|
||||
char name[MAX_SET_NAME_LENGTH];
|
||||
unsigned char loopedVolume;
|
||||
unsigned int time_start, time_end;
|
||||
unsigned int volRange_start, volRange_end;
|
||||
unsigned char numSubWaves;
|
||||
int subWaves[MAX_WAVES_PER_GROUP];
|
||||
int loopedWave;
|
||||
int radius; //NOTENOTE: -1 is global
|
||||
int masterVolume; //Used for fading ambient sets (not a byte to prevent wrapping)
|
||||
int id; //Used for easier referencing of sets
|
||||
int fadeTime; //When the fade was started on this set
|
||||
} ambientSet_t;
|
||||
|
||||
typedef void (*parseFunc_t)( ambientSet_t & );
|
||||
|
||||
// Classes
|
||||
|
||||
//NOTENOTE: But this one should be a class because of all the mapping and internal data handling
|
||||
class CSetGroup
|
||||
{
|
||||
public:
|
||||
|
||||
CSetGroup();
|
||||
~CSetGroup();
|
||||
|
||||
void Init( void )
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
void Free( void );
|
||||
|
||||
ambientSet_t *AddSet( const char *name );
|
||||
|
||||
ambientSet_t *GetSet ( const char *name );
|
||||
ambientSet_t *GetSet ( int ID );
|
||||
|
||||
protected:
|
||||
|
||||
int m_numSets;
|
||||
vector < ambientSet_t * > *m_ambientSets;
|
||||
map < sstring_t, ambientSet_t * > *m_setMap;
|
||||
};
|
||||
|
||||
// Prototypes
|
||||
|
||||
extern void AS_Init( void );
|
||||
extern void AS_Free( void );
|
||||
extern void AS_ParseSets( void );
|
||||
extern void AS_AddPrecacheEntry( const char *name );
|
||||
|
||||
extern void S_UpdateAmbientSet ( const char *name, vec3_t origin );
|
||||
extern int S_AddLocalSet( const char *name, vec3_t origin, int time );
|
||||
|
||||
extern sfxHandle_t AS_GetBModelSound( const char *name, int stage );
|
||||
|
||||
#endif //__SND_AMBIENT__
|
||||
6276
code/client/snd_dma.cpp
Normal file
6276
code/client/snd_dma.cpp
Normal file
File diff suppressed because it is too large
Load Diff
3259
code/client/snd_dma_console.cpp
Normal file
3259
code/client/snd_dma_console.cpp
Normal file
File diff suppressed because it is too large
Load Diff
228
code/client/snd_local.h
Normal file
228
code/client/snd_local.h
Normal file
@@ -0,0 +1,228 @@
|
||||
// snd_local.h -- private sound definations
|
||||
|
||||
#ifndef SND_LOCAL_H
|
||||
#define SND_LOCAL_H
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "snd_public.h"
|
||||
#include "../mp3code/mp3struct.h"
|
||||
|
||||
// Open AL Specific
|
||||
#include "openal\al.h"
|
||||
#include "openal\alc.h"
|
||||
#include "eax\eax.h"
|
||||
#include "eax\eaxman.h"
|
||||
|
||||
// Added for Open AL to know when to mute all sounds (e.g when app. loses focus)
|
||||
void S_AL_MuteAllSounds(qboolean bMute);
|
||||
|
||||
|
||||
//from SND_AMBIENT
|
||||
extern void AS_Init( void );
|
||||
extern void AS_Free( void );
|
||||
|
||||
|
||||
#define PAINTBUFFER_SIZE 1024
|
||||
|
||||
|
||||
// !!! if this is changed, the asm code must change !!!
|
||||
typedef struct {
|
||||
int left; // the final values will be clamped to +/- 0x00ffff00 and shifted down
|
||||
int right;
|
||||
} portable_samplepair_t;
|
||||
|
||||
|
||||
// keep this enum in sync with the table "sSoundCompressionMethodStrings" -ste
|
||||
//
|
||||
typedef enum
|
||||
{
|
||||
ct_16 = 0, // formerly ct_NONE in EF1, now indicates 16-bit samples (the default)
|
||||
ct_MP3,
|
||||
//
|
||||
ct_NUMBEROF // used only for array sizing
|
||||
|
||||
} SoundCompressionMethod_t;
|
||||
|
||||
|
||||
typedef struct sfx_s {
|
||||
short *pSoundData;
|
||||
bool bDefaultSound; // couldn't be loaded, so use buzz
|
||||
bool bInMemory; // not in Memory, set qtrue when loaded, and qfalse when its buffers are freed up because of being old, so can be reloaded
|
||||
short iLastLevelUsedOn; // used for cacheing purposes
|
||||
SoundCompressionMethod_t eSoundCompressionMethod;
|
||||
MP3STREAM *pMP3StreamHeader; // NULL ptr unless this sfx_t is an MP3. Use Z_Malloc and Z_Free
|
||||
int iSoundLengthInSamples; // length in samples, always kept as 16bit now so this is #shorts (watch for stereo later for music?)
|
||||
char sSoundName[MAX_QPATH];
|
||||
int iLastTimeUsed;
|
||||
float fVolRange; // used to set the highest volume this sample has at load time - used for lipsynching
|
||||
|
||||
// Open AL
|
||||
ALuint Buffer;
|
||||
char *lipSyncData;
|
||||
|
||||
struct sfx_s *next; // only used because of hash table when registering
|
||||
} sfx_t;
|
||||
|
||||
typedef struct {
|
||||
int channels;
|
||||
int samples; // mono samples in buffer
|
||||
int submission_chunk; // don't mix less than this #
|
||||
int samplebits;
|
||||
int speed;
|
||||
byte *buffer;
|
||||
} dma_t;
|
||||
|
||||
|
||||
#define START_SAMPLE_IMMEDIATE 0x7fffffff
|
||||
|
||||
// Open AL specific
|
||||
typedef struct
|
||||
{
|
||||
ALuint BufferID;
|
||||
ALuint Status;
|
||||
char *Data;
|
||||
} STREAMINGBUFFER;
|
||||
|
||||
#define NUM_STREAMING_BUFFERS 4
|
||||
#define STREAMING_BUFFER_SIZE 4608 // 4 decoded MP3 frames
|
||||
|
||||
#define QUEUED 1
|
||||
#define UNQUEUED 2
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// back-indented fields new in TA codebase, will re-format when MP3 code finished -ste
|
||||
// note: field missing in TA: qboolean loopSound; // from an S_AddLoopSound call, cleared each frame
|
||||
//
|
||||
int startSample; // START_SAMPLE_IMMEDIATE = set immediately on next mix
|
||||
int entnum; // to allow overriding a specific sound
|
||||
soundChannel_t entchannel; // to allow overriding a specific sound
|
||||
int leftvol; // 0-255 volume after spatialization
|
||||
int rightvol; // 0-255 volume after spatialization
|
||||
int master_vol; // 0-255 volume before spatialization
|
||||
|
||||
|
||||
vec3_t origin; // only use if fixed_origin is set
|
||||
|
||||
qboolean fixed_origin; // use origin instead of fetching entnum's origin
|
||||
sfx_t *thesfx; // sfx structure
|
||||
qboolean loopSound; // from an S_AddLoopSound call, cleared each frame
|
||||
//
|
||||
MP3STREAM MP3StreamHeader;
|
||||
byte MP3SlidingDecodeBuffer[50000/*12000*/]; // typical back-request = -3072, so roughly double is 6000 (safety), then doubled again so the 6K pos is in the middle of the buffer)
|
||||
int iMP3SlidingDecodeWritePos;
|
||||
int iMP3SlidingDecodeWindowPos;
|
||||
|
||||
|
||||
// Open AL specific
|
||||
bool bLooping; // Signifies if this channel / source is playing a looping sound
|
||||
// bool bAmbient; // Signifies if this channel / source is playing a looping ambient sound
|
||||
bool bProcessed; // Signifies if this channel / source has been processed
|
||||
bool bStreaming; // Set to true if the data needs to be streamed (MP3 or dialogue)
|
||||
STREAMINGBUFFER buffers[NUM_STREAMING_BUFFERS]; // AL Buffers for streaming
|
||||
ALuint alSource; // Open AL Source
|
||||
bool bPlaying; // Set to true when a sound is playing on this channel / source
|
||||
int iStartTime; // Time playback of Source begins
|
||||
int lSlotID; // ID of Slot rendering Source's environment (enables a send to this FXSlot)
|
||||
} channel_t;
|
||||
|
||||
|
||||
#define WAV_FORMAT_PCM 1
|
||||
#define WAV_FORMAT_ADPCM 2 // not actually implemented, but is the value that you get in a header
|
||||
#define WAV_FORMAT_MP3 3 // not actually used this way, but just ensures we don't match one of the legit formats
|
||||
|
||||
|
||||
typedef struct {
|
||||
int format;
|
||||
int rate;
|
||||
int width;
|
||||
int channels;
|
||||
int samples;
|
||||
int dataofs; // chunk starts this many bytes from file start
|
||||
} wavinfo_t;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
====================================================================
|
||||
|
||||
SYSTEM SPECIFIC FUNCTIONS
|
||||
|
||||
====================================================================
|
||||
*/
|
||||
|
||||
// initializes cycling through a DMA buffer and returns information on it
|
||||
qboolean SNDDMA_Init(void);
|
||||
|
||||
// gets the current DMA position
|
||||
int SNDDMA_GetDMAPos(void);
|
||||
|
||||
// shutdown the DMA xfer.
|
||||
void SNDDMA_Shutdown(void);
|
||||
|
||||
void SNDDMA_BeginPainting (void);
|
||||
|
||||
void SNDDMA_Submit(void);
|
||||
|
||||
//====================================================================
|
||||
|
||||
#define MAX_CHANNELS 32
|
||||
extern channel_t s_channels[MAX_CHANNELS];
|
||||
|
||||
extern int s_paintedtime;
|
||||
extern int s_rawend;
|
||||
extern vec3_t listener_origin;
|
||||
extern vec3_t listener_forward;
|
||||
extern vec3_t listener_right;
|
||||
extern vec3_t listener_up;
|
||||
extern dma_t dma;
|
||||
|
||||
#define MAX_RAW_SAMPLES 16384
|
||||
extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
|
||||
portable_samplepair_t *S_GetRawSamplePointer(); // TA added this, but it just returns the s_rawsamples[] array above. Oh well...
|
||||
|
||||
extern cvar_t *s_volume;
|
||||
extern cvar_t *s_volumeVoice;
|
||||
extern cvar_t *s_nosound;
|
||||
extern cvar_t *s_khz;
|
||||
extern cvar_t *s_allowDynamicMusic;
|
||||
extern cvar_t *s_show;
|
||||
extern cvar_t *s_mixahead;
|
||||
|
||||
extern cvar_t *s_testsound;
|
||||
extern cvar_t *s_separation;
|
||||
|
||||
wavinfo_t GetWavinfo (const char *name, byte *wav, int wavlength);
|
||||
|
||||
qboolean S_LoadSound( sfx_t *sfx );
|
||||
|
||||
|
||||
void S_PaintChannels(int endtime);
|
||||
|
||||
// picks a channel based on priorities, empty slots, number of channels
|
||||
channel_t *S_PickChannel(int entnum, int entchannel);
|
||||
|
||||
// spatializes a channel
|
||||
void S_Spatialize(channel_t *ch);
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
//
|
||||
// new stuff from TA codebase
|
||||
|
||||
byte *SND_malloc(int iSize, sfx_t *sfx);
|
||||
void SND_setup();
|
||||
int SND_FreeOldestSound(sfx_t *pButNotThisOne = NULL);
|
||||
void SND_TouchSFX(sfx_t *sfx);
|
||||
|
||||
void S_DisplayFreeMemory(void);
|
||||
void S_memoryLoad(sfx_t *sfx);
|
||||
//
|
||||
//////////////////////////////////
|
||||
|
||||
#include "cl_mp3.h"
|
||||
|
||||
#endif // #ifndef SND_LOCAL_H
|
||||
|
||||
141
code/client/snd_local_console.h
Normal file
141
code/client/snd_local_console.h
Normal file
@@ -0,0 +1,141 @@
|
||||
// snd_local.h -- private sound definations
|
||||
|
||||
#ifndef SND_LOCAL_H
|
||||
#define SND_LOCAL_H
|
||||
|
||||
// Following #define is ONLY for MP JKA code.
|
||||
// They want to keep qboolean pure enum in that code, so all
|
||||
// sound code uses sboolean.
|
||||
#define sboolean int
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "snd_public.h"
|
||||
#include "../mp3code/mp3struct.h"
|
||||
|
||||
#include "openal/al.h"
|
||||
#include "openal/alc.h"
|
||||
|
||||
typedef int streamHandle_t;
|
||||
|
||||
//from SND_AMBIENT
|
||||
extern void AS_Init( void );
|
||||
extern void AS_Free( void );
|
||||
|
||||
//Changing this? It needs to be synced with the create_soundbank util.
|
||||
enum SoundFilenameFlags
|
||||
{
|
||||
SFF_WEAPONS_ATST,
|
||||
SFF_SAND_CREATURE,
|
||||
SFF_HOWLER,
|
||||
SFF_ALTCHARGE,
|
||||
SFF_FALLING,
|
||||
SFF_TIEEXPLODE,
|
||||
//Can't have more than 8.
|
||||
};
|
||||
//Changing this? It needs to be synced with the create_soundbank util.
|
||||
|
||||
typedef struct {
|
||||
int format;
|
||||
int size;
|
||||
int width;
|
||||
int rate;
|
||||
int samples;
|
||||
} wavinfo_t;
|
||||
|
||||
extern wavinfo_t GetWavInfo(byte *data);
|
||||
|
||||
|
||||
#define SFX_FLAG_UNLOADED (1 << 0)
|
||||
#define SFX_FLAG_LOADING (1 << 1)
|
||||
#define SFX_FLAG_RESIDENT (1 << 2)
|
||||
#define SFX_FLAG_DEFAULT (1 << 3)
|
||||
#define SFX_FLAG_DEMAND (1 << 4)
|
||||
#define SFX_FLAG_VOICE (1 << 5)
|
||||
|
||||
typedef struct sfx_s {
|
||||
int iFlags;
|
||||
int iSoundLength; // length in bytes
|
||||
int iLastTimeUsed; // last time sound was played in ms
|
||||
unsigned int iFileCode; // CRC of the file name
|
||||
streamHandle_t iStreamHandle; // handle to the sound file when reading
|
||||
void* pSoundData; // buffer to hold sound as we are loading it
|
||||
char* pLipSyncData; // buffer to hold lip sync information on characters
|
||||
// store the total number of samples in the first 4 bytes
|
||||
// followed by the actual lipsync data in the remaining bytes
|
||||
ALuint Buffer;
|
||||
|
||||
//char* sSoundName; // added for debugging
|
||||
} sfx_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int entnum; // to allow overriding a specific sound
|
||||
int entchannel; // to allow overriding a specific sound
|
||||
int master_vol; // 0-255 volume before spatialization
|
||||
float fLastVolume; // 0-1 last volume sent to AL
|
||||
|
||||
vec3_t origin; // sound location
|
||||
bool bOriginDirty; // does the AL position need to be updated
|
||||
|
||||
sfx_t *thesfx; // sfx structure
|
||||
|
||||
int loopChannel; // index into loopSounds (if appropriate)
|
||||
|
||||
bool bPlaying; // Set to true when a sound is playing on this channel / source
|
||||
bool b2D; // Signifies a 2d sound
|
||||
bool bLooping; // Signifies if this channel / source is playing a looping sound
|
||||
ALuint alSource; // Open AL Source
|
||||
|
||||
unsigned int iLastPlayTime; // Last time a sound was played on this channel
|
||||
} channel_t;
|
||||
|
||||
extern cvar_t *s_nosound;
|
||||
extern cvar_t *s_allowDynamicMusic;
|
||||
extern cvar_t *s_show;
|
||||
|
||||
extern cvar_t *s_testsound;
|
||||
extern cvar_t *s_separation;
|
||||
|
||||
extern int* s_entityWavVol;
|
||||
|
||||
int Sys_GetFileCode( const char* sSoundName );
|
||||
int S_GetFileCode( const char* sSoundName );
|
||||
|
||||
qboolean S_StartLoadSound( sfx_t *sfx );
|
||||
qboolean S_EndLoadSound( sfx_t *sfx );
|
||||
|
||||
void S_InitLoad(void);
|
||||
void S_CloseLoad(void);
|
||||
void S_UpdateLoading(void);
|
||||
|
||||
// New stuff from VV
|
||||
void S_LoadSound( sfxHandle_t sfxHandle );
|
||||
|
||||
// picks a channel based on priorities, empty slots, number of channels
|
||||
channel_t *S_PickChannel(int entnum, int entchannel);
|
||||
|
||||
//////////////////////////////////
|
||||
//
|
||||
// new stuff from TA codebase
|
||||
|
||||
void SND_update(sfx_t *sfx);
|
||||
void SND_setup();
|
||||
int SND_FreeOldestSound(sfx_t *pButNotThisOne = NULL);
|
||||
void SND_TouchSFX(sfx_t *sfx);
|
||||
|
||||
void S_DisplayFreeMemory(void);
|
||||
void S_memoryLoad(sfx_t *sfx);
|
||||
void S_PreProcessLipSync(sfx_t *sfx);
|
||||
|
||||
bool Sys_StreamIsReading(streamHandle_t handle);
|
||||
int Sys_StreamOpen(int code, streamHandle_t *handle);
|
||||
bool Sys_StreamRead(void* buffer, int size, int pos, streamHandle_t handle);
|
||||
void Sys_StreamClose(streamHandle_t handle);
|
||||
bool Sys_StreamIsError(streamHandle_t handle);
|
||||
|
||||
//
|
||||
//////////////////////////////////
|
||||
|
||||
#endif // #ifndef SND_LOCAL_H
|
||||
|
||||
1015
code/client/snd_mem.cpp
Normal file
1015
code/client/snd_mem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
368
code/client/snd_mem_console.cpp
Normal file
368
code/client/snd_mem_console.cpp
Normal file
@@ -0,0 +1,368 @@
|
||||
// snd_mem.c: sound caching
|
||||
|
||||
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
// #include "../server/exe_headers.h"
|
||||
|
||||
#include "snd_local_console.h"
|
||||
|
||||
#ifdef _XBOX
|
||||
#include <xtl.h>
|
||||
#endif
|
||||
|
||||
#define SND_MAX_LOADS 48
|
||||
static sfx_t** s_LoadList = NULL;
|
||||
static int s_LoadListSize = 0;
|
||||
qboolean gbInsideLoadSound = qfalse; // Needed to link VVFIXME
|
||||
|
||||
extern int Sys_GetFileCode(const char *name);
|
||||
|
||||
//Drain sound main memory into ARAM.
|
||||
void S_DrainRawSoundData(void)
|
||||
{
|
||||
extern int s_soundStarted;
|
||||
if (!s_soundStarted) return;
|
||||
|
||||
do
|
||||
{
|
||||
S_UpdateLoading();
|
||||
|
||||
#ifdef _GAMECUBE
|
||||
extern void ERR_DiscFail(bool);
|
||||
ERR_DiscFail(true);
|
||||
#endif
|
||||
}
|
||||
while (s_LoadListSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
============
|
||||
GetWavInfo
|
||||
============
|
||||
*/
|
||||
wavinfo_t GetWavInfo(byte *data)
|
||||
{
|
||||
wavinfo_t info;
|
||||
memset(&info, 0, sizeof(wavinfo_t));
|
||||
|
||||
if (!data) return info;
|
||||
|
||||
#ifdef _GAMECUBE
|
||||
if (*(short*)&data[14] != 0)
|
||||
{
|
||||
// invalid type, abort
|
||||
return info;
|
||||
}
|
||||
|
||||
info.format = AL_FORMAT_MONO4;
|
||||
info.width = 4;
|
||||
info.size = ((*(int*)&data[20]) >> 1) + 96;
|
||||
info.rate = *(int*)&data[8];
|
||||
#else
|
||||
int dataofs = 0;
|
||||
if (strncmp((char *)&data[dataofs + 0], "RIFF", 4) ||
|
||||
strncmp((char *)&data[dataofs + 8], "WAVE", 4))
|
||||
{
|
||||
// invalid type, abort
|
||||
return info;
|
||||
}
|
||||
dataofs += 12; // done with riff chunk
|
||||
|
||||
WAVEFORMATEX* wav = (WAVEFORMATEX*)&data[dataofs + 8];
|
||||
info.format = wav->nChannels == 1 ? AL_FORMAT_MONO4 : AL_FORMAT_STEREO4;
|
||||
info.rate = wav->nSamplesPerSec;
|
||||
info.width = wav->wBitsPerSample;
|
||||
dataofs += sizeof(WAVEFORMATEX) + wav->cbSize + 8; // done with fmt chunk
|
||||
|
||||
info.size = *(int*)&data[dataofs + 4];
|
||||
info.samples = (info.size * 2);
|
||||
|
||||
dataofs += 8; // done with data chunk
|
||||
#endif
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
// adjust filename for foreign languages and WAV/MP3 issues.
|
||||
//
|
||||
unsigned int Sys_GetSoundFileCode(const char* name);
|
||||
int Sys_GetSoundFileCodeSize(unsigned int filecode);
|
||||
static qboolean S_LoadSound_FileNameAdjuster(char *psFilename)
|
||||
{
|
||||
const char* ext = "wxb";
|
||||
|
||||
int len = strlen(psFilename);
|
||||
|
||||
char *psVoice = strstr(psFilename,"chars");
|
||||
if (psVoice)
|
||||
{
|
||||
// account for foreign voices...
|
||||
//
|
||||
extern DWORD g_dwLanguage;
|
||||
if (g_dwLanguage == XC_LANGUAGE_GERMAN)
|
||||
strncpy(psVoice, "chr_d", 5); // Same number of letters as "chars"
|
||||
else if (g_dwLanguage == XC_LANGUAGE_FRENCH)
|
||||
strncpy(psVoice, "chr_f", 5); // Same number of letters as "chars"
|
||||
else
|
||||
psVoice = NULL; // Flag that we didn't substitute
|
||||
}
|
||||
|
||||
psFilename[len-3] = ext[0];
|
||||
psFilename[len-2] = ext[1];
|
||||
psFilename[len-1] = ext[2];
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
if(psFilename[i] == '/')
|
||||
{
|
||||
psFilename[i] = '\\';
|
||||
}
|
||||
}
|
||||
unsigned int code = Sys_GetSoundFileCode( psFilename );
|
||||
|
||||
if(Sys_GetSoundFileCodeSize(code) == -1)
|
||||
{
|
||||
code = -1;
|
||||
}
|
||||
|
||||
if ( code == -1 )
|
||||
{
|
||||
//hmmm, not found, ok, maybe we were trying a foreign noise ("arghhhhh.mp3" that doesn't matter?) but it
|
||||
// was missing? Can't tell really, since both types are now in sound/chars. Oh well, fall back to English for now...
|
||||
|
||||
if (psVoice) // were we trying to load foreign?
|
||||
{
|
||||
// yep, so fallback to re-try the english...
|
||||
//
|
||||
strncpy(psVoice,"chars",5);
|
||||
|
||||
psFilename[len-3] = ext[0];
|
||||
psFilename[len-2] = ext[1];
|
||||
psFilename[len-1] = ext[2];
|
||||
code = Sys_GetSoundFileCode( psFilename );
|
||||
}
|
||||
}
|
||||
|
||||
if(Sys_GetSoundFileCodeSize(code) == -1)
|
||||
{
|
||||
code = -1;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
S_GetFileCode
|
||||
==============
|
||||
*/
|
||||
int S_GetFileCode( const char* sSoundName )
|
||||
{
|
||||
char sLoadName[MAX_QPATH];
|
||||
|
||||
// make up a local filename to try wav/mp3 substitutes...
|
||||
//
|
||||
Q_strncpyz(sLoadName, sSoundName, sizeof(sLoadName));
|
||||
Q_strlwr( sLoadName );
|
||||
|
||||
// make sure we have an extension...
|
||||
//
|
||||
if (sLoadName[strlen(sLoadName) - 4] != '.')
|
||||
{
|
||||
strcat(sLoadName, ".xxx");
|
||||
}
|
||||
|
||||
return S_LoadSound_FileNameAdjuster(sLoadName);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
S_UpdateLoading
|
||||
============
|
||||
*/
|
||||
void S_UpdateLoading(void) {
|
||||
for ( int i = 0; i < SND_MAX_LOADS; ++i )
|
||||
{
|
||||
if ( s_LoadList[i] &&
|
||||
(s_LoadList[i]->iFlags & SFX_FLAG_LOADING) &&
|
||||
!Sys_StreamIsReading(s_LoadList[i]->iStreamHandle) )
|
||||
{
|
||||
S_EndLoadSound(s_LoadList[i]);
|
||||
s_LoadList[i] = NULL;
|
||||
--s_LoadListSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
S_BeginLoadSound
|
||||
==============
|
||||
*/
|
||||
qboolean S_StartLoadSound( sfx_t *sfx )
|
||||
{
|
||||
assert(sfx->iFlags & SFX_FLAG_UNLOADED);
|
||||
sfx->iFlags &= ~SFX_FLAG_UNLOADED;
|
||||
|
||||
// Valid file?
|
||||
if (sfx->iFileCode == -1)
|
||||
{
|
||||
sfx->iFlags |= SFX_FLAG_RESIDENT | SFX_FLAG_DEFAULT;
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
#if PROFILE_SOUND
|
||||
extern char* Sys_GetSoundName( unsigned int crc );
|
||||
char* name = Sys_GetSoundName(sfx->iFileCode);
|
||||
int time = Sys_Milliseconds();
|
||||
Com_Printf("SOUND: %s at %d\n", name, time);
|
||||
#endif
|
||||
|
||||
// Finish up any pending loads
|
||||
do
|
||||
{
|
||||
S_UpdateLoading();
|
||||
}
|
||||
while (s_LoadListSize >= SND_MAX_LOADS);
|
||||
|
||||
// Open the file
|
||||
sfx->iSoundLength = Sys_StreamOpen(sfx->iFileCode, &sfx->iStreamHandle);
|
||||
if ( sfx->iSoundLength <= 0 )
|
||||
{
|
||||
sfx->iFlags |= SFX_FLAG_RESIDENT | SFX_FLAG_DEFAULT;
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
#ifdef _GAMECUBE
|
||||
// Allocate a buffer to read into...
|
||||
sfx->pSoundData = Z_Malloc(sfx->iSoundLength + 64, TAG_SND_RAWDATA,
|
||||
qtrue, 32);
|
||||
#else
|
||||
// Allocate a buffer to read into...
|
||||
sfx->pSoundData = Z_Malloc(sfx->iSoundLength, TAG_SND_RAWDATA, qtrue, 32);
|
||||
#endif
|
||||
|
||||
// Setup the background read
|
||||
if ( !sfx->pSoundData ||
|
||||
!Sys_StreamRead(sfx->pSoundData, sfx->iSoundLength, 0,
|
||||
sfx->iStreamHandle) )
|
||||
{
|
||||
if(sfx->pSoundData) {
|
||||
Z_Free(sfx->pSoundData);
|
||||
}
|
||||
Sys_StreamClose(sfx->iStreamHandle);
|
||||
sfx->iFlags |= SFX_FLAG_RESIDENT | SFX_FLAG_DEFAULT;
|
||||
return qfalse;
|
||||
}
|
||||
sfx->iFlags |= SFX_FLAG_LOADING;
|
||||
|
||||
// add sound to load list
|
||||
for (int i = 0; i < SND_MAX_LOADS; ++i)
|
||||
{
|
||||
if (!s_LoadList[i])
|
||||
{
|
||||
s_LoadList[i] = sfx;
|
||||
++s_LoadListSize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
S_EndLoadSound
|
||||
==============
|
||||
*/
|
||||
qboolean S_EndLoadSound( sfx_t *sfx )
|
||||
{
|
||||
wavinfo_t info;
|
||||
byte* data;
|
||||
ALuint Buffer;
|
||||
|
||||
assert(sfx->iFlags & SFX_FLAG_LOADING);
|
||||
sfx->iFlags &= ~SFX_FLAG_LOADING;
|
||||
|
||||
// was the read successful?
|
||||
if (Sys_StreamIsError(sfx->iStreamHandle))
|
||||
{
|
||||
#if defined(FINAL_BUILD)
|
||||
extern void ERR_DiscFail(bool);
|
||||
ERR_DiscFail(false);
|
||||
#endif
|
||||
Sys_StreamClose(sfx->iStreamHandle);
|
||||
Z_Free(sfx->pSoundData);
|
||||
sfx->iFlags |= SFX_FLAG_RESIDENT | SFX_FLAG_DEFAULT;
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
Sys_StreamClose(sfx->iStreamHandle);
|
||||
SND_TouchSFX(sfx);
|
||||
|
||||
sfx->iLastTimeUsed = Com_Milliseconds()+1; // why +1? Hmmm, leave it for now I guess
|
||||
|
||||
// loading a WAV, presumably...
|
||||
data = (byte*)sfx->pSoundData;
|
||||
info = GetWavInfo( data );
|
||||
|
||||
if (info.size == 0)
|
||||
{
|
||||
Z_Free(sfx->pSoundData);
|
||||
sfx->iFlags |= SFX_FLAG_RESIDENT | SFX_FLAG_DEFAULT;
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
sfx->iSoundLength = info.size;
|
||||
|
||||
// make sure we have enough space for the sound
|
||||
SND_update(sfx);
|
||||
|
||||
// Clear Open AL Error State
|
||||
alGetError();
|
||||
|
||||
// Generate AL Buffer
|
||||
alGenBuffers(1, &Buffer);
|
||||
|
||||
// Copy audio data to AL Buffer
|
||||
alBufferData(Buffer, info.format, data,
|
||||
sfx->iSoundLength, info.rate);
|
||||
if (alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
Z_Free(sfx->pSoundData);
|
||||
sfx->iFlags |= SFX_FLAG_UNLOADED;
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
sfx->Buffer = Buffer;
|
||||
|
||||
#ifdef _GAMECUBE
|
||||
Z_Free(sfx->pSoundData);
|
||||
#endif
|
||||
sfx->iFlags |= SFX_FLAG_RESIDENT;
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
S_InitLoad
|
||||
============
|
||||
*/
|
||||
void S_InitLoad(void) {
|
||||
s_LoadList = new sfx_t*[SND_MAX_LOADS];
|
||||
memset(s_LoadList, 0, SND_MAX_LOADS * sizeof(sfx_t*));
|
||||
s_LoadListSize = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
S_CloseLoad
|
||||
============
|
||||
*/
|
||||
void S_CloseLoad(void) {
|
||||
delete [] s_LoadList;
|
||||
}
|
||||
|
||||
471
code/client/snd_mix.cpp
Normal file
471
code/client/snd_mix.cpp
Normal file
@@ -0,0 +1,471 @@
|
||||
// snd_mix.c -- portable code to mix sounds for snd_dma.c
|
||||
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#include "../server/exe_headers.h"
|
||||
|
||||
|
||||
|
||||
#include "snd_local.h"
|
||||
|
||||
portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];
|
||||
int *snd_p, snd_linear_count, snd_vol;
|
||||
short *snd_out;
|
||||
|
||||
|
||||
|
||||
|
||||
#if !(defined __linux__ && defined __i386__)
|
||||
#if !id386
|
||||
|
||||
|
||||
void S_WriteLinearBlastStereo16 (void)
|
||||
{
|
||||
int i;
|
||||
int val;
|
||||
|
||||
for (i=0 ; i<snd_linear_count ; i+=2)
|
||||
{
|
||||
val = snd_p[i]>>8;
|
||||
if (val > 0x7fff)
|
||||
snd_out[i] = 0x7fff;
|
||||
else if (val < (short)0x8000)
|
||||
snd_out[i] = (short)0x8000;
|
||||
else
|
||||
snd_out[i] = val;
|
||||
|
||||
val = snd_p[i+1]>>8;
|
||||
if (val > 0x7fff)
|
||||
snd_out[i+1] = 0x7fff;
|
||||
else if (val < (short)0x8000)
|
||||
snd_out[i+1] = (short)0x8000;
|
||||
else
|
||||
snd_out[i+1] = val;
|
||||
}
|
||||
}
|
||||
#else
|
||||
unsigned int uiMMXAvailable = 0; // leave as 32 bit
|
||||
__declspec( naked ) void S_WriteLinearBlastStereo16 (void)
|
||||
{
|
||||
__asm {
|
||||
|
||||
push edi
|
||||
push ebx
|
||||
|
||||
mov ecx,ds:dword ptr[snd_linear_count] // snd_linear_count is always even at this point, but not nec. mult of 4
|
||||
mov ebx,ds:dword ptr[snd_p]
|
||||
mov edi,ds:dword ptr[snd_out]
|
||||
|
||||
cmp [uiMMXAvailable], dword ptr 0
|
||||
je NoMMX
|
||||
|
||||
// writes 8 items (128 bits) per loop pass...
|
||||
//
|
||||
cmp ecx,8
|
||||
jb NoMMX
|
||||
|
||||
LWLBLoopTop_MMX:
|
||||
|
||||
movq mm1,[-8+ebx+ecx*4]
|
||||
movq mm0,[-16+ebx+ecx*4]
|
||||
movq mm3,[-24+ebx+ecx*4]
|
||||
movq mm2,[-32+ebx+ecx*4]
|
||||
psrad mm0,8
|
||||
psrad mm1,8
|
||||
psrad mm2,8
|
||||
psrad mm3,8
|
||||
packssdw mm0,mm1
|
||||
packssdw mm2,mm3
|
||||
movq [-8+edi+ecx*2],mm0
|
||||
movq [-16+edi+ecx*2],mm2
|
||||
|
||||
sub ecx,8
|
||||
cmp ecx,8
|
||||
jae LWLBLoopTop_MMX
|
||||
|
||||
emms
|
||||
|
||||
// now deal with any remaining count...
|
||||
//
|
||||
jecxz LExit
|
||||
|
||||
NoMMX:
|
||||
|
||||
// writes 2 items (32 bits) per loop pass...
|
||||
//
|
||||
LWLBLoopTop:
|
||||
mov eax,ds:dword ptr[-8+ebx+ecx*4]
|
||||
sar eax,8
|
||||
cmp eax,07FFFh
|
||||
jg LClampHigh
|
||||
cmp eax,0FFFF8000h
|
||||
jnl LClampDone
|
||||
mov eax,0FFFF8000h
|
||||
jmp LClampDone
|
||||
LClampHigh:
|
||||
mov eax,07FFFh
|
||||
LClampDone:
|
||||
mov edx,ds:dword ptr[-4+ebx+ecx*4]
|
||||
sar edx,8
|
||||
cmp edx,07FFFh
|
||||
jg LClampHigh2
|
||||
cmp edx,0FFFF8000h
|
||||
jnl LClampDone2
|
||||
mov edx,0FFFF8000h
|
||||
jmp LClampDone2
|
||||
LClampHigh2:
|
||||
mov edx,07FFFh
|
||||
LClampDone2:
|
||||
shl edx,16
|
||||
and eax,0FFFFh
|
||||
or edx,eax
|
||||
mov ds:dword ptr[-4+edi+ecx*2],edx
|
||||
|
||||
sub ecx,2
|
||||
jnz LWLBLoopTop
|
||||
|
||||
LExit:
|
||||
pop ebx
|
||||
pop edi
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
void S_TransferStereo16 (unsigned long *pbuf, int endtime)
|
||||
{
|
||||
int lpos;
|
||||
int ls_paintedtime;
|
||||
|
||||
snd_p = (int *) paintbuffer;
|
||||
ls_paintedtime = s_paintedtime;
|
||||
|
||||
while (ls_paintedtime < endtime)
|
||||
{
|
||||
// handle recirculating buffer issues
|
||||
lpos = ls_paintedtime & ((dma.samples>>1)-1);
|
||||
|
||||
snd_out = (short *) pbuf + (lpos<<1);
|
||||
|
||||
snd_linear_count = (dma.samples>>1) - lpos;
|
||||
if (ls_paintedtime + snd_linear_count > endtime)
|
||||
snd_linear_count = endtime - ls_paintedtime;
|
||||
|
||||
snd_linear_count <<= 1;
|
||||
|
||||
// write a linear blast of samples
|
||||
S_WriteLinearBlastStereo16 ();
|
||||
|
||||
snd_p += snd_linear_count;
|
||||
ls_paintedtime += (snd_linear_count>>1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
===================
|
||||
S_TransferPaintBuffer
|
||||
|
||||
===================
|
||||
*/
|
||||
void S_TransferPaintBuffer(int endtime)
|
||||
{
|
||||
int out_idx;
|
||||
int count;
|
||||
int out_mask;
|
||||
int *p;
|
||||
int step;
|
||||
int val;
|
||||
unsigned long *pbuf;
|
||||
|
||||
pbuf = (unsigned long *)dma.buffer;
|
||||
|
||||
|
||||
if ( s_testsound->integer ) {
|
||||
int i;
|
||||
int count;
|
||||
|
||||
// write a fixed sine wave
|
||||
count = (endtime - s_paintedtime);
|
||||
for (i=0 ; i<count ; i++)
|
||||
paintbuffer[i].left = paintbuffer[i].right = (int)(sin((s_paintedtime+i)*0.1)*20000*256);
|
||||
}
|
||||
|
||||
|
||||
if (dma.samplebits == 16 && dma.channels == 2)
|
||||
{ // optimized case
|
||||
S_TransferStereo16 (pbuf, endtime);
|
||||
}
|
||||
else
|
||||
{ // general case
|
||||
p = (int *) paintbuffer;
|
||||
count = (endtime - s_paintedtime) * dma.channels;
|
||||
out_mask = dma.samples - 1;
|
||||
out_idx = s_paintedtime * dma.channels & out_mask;
|
||||
step = 3 - dma.channels;
|
||||
|
||||
if (dma.samplebits == 16)
|
||||
{
|
||||
short *out = (short *) pbuf;
|
||||
while (count--)
|
||||
{
|
||||
val = *p >> 8;
|
||||
p+= step;
|
||||
if (val > 0x7fff)
|
||||
val = 0x7fff;
|
||||
else if (val < (short)0x8000)
|
||||
val = (short)0x8000;
|
||||
out[out_idx] = (short)val;
|
||||
out_idx = (out_idx + 1) & out_mask;
|
||||
}
|
||||
}
|
||||
else if (dma.samplebits == 8)
|
||||
{
|
||||
unsigned char *out = (unsigned char *) pbuf;
|
||||
while (count--)
|
||||
{
|
||||
val = *p >> 8;
|
||||
p+= step;
|
||||
if (val > 0x7fff)
|
||||
val = 0x7fff;
|
||||
else if (val < (short)0x8000)
|
||||
val = (short)0x8000;
|
||||
out[out_idx] = (short)((val>>8) + 128);
|
||||
out_idx = (out_idx + 1) & out_mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
CHANNEL MIXING
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
static void S_PaintChannelFrom16( channel_t *ch, const sfx_t *sfx, int count, int sampleOffset, int bufferOffset )
|
||||
{
|
||||
portable_samplepair_t *pSamplesDest;
|
||||
int iData;
|
||||
|
||||
|
||||
int iLeftVol = ch->leftvol * snd_vol;
|
||||
int iRightVol = ch->rightvol * snd_vol;
|
||||
|
||||
pSamplesDest = &paintbuffer[ bufferOffset ];
|
||||
|
||||
for ( int i=0 ; i<count ; i++ )
|
||||
{
|
||||
iData = sfx->pSoundData[ sampleOffset++ ];
|
||||
|
||||
pSamplesDest[i].left += (iData * iLeftVol )>>8;
|
||||
pSamplesDest[i].right += (iData * iRightVol)>>8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void S_PaintChannelFromMP3( channel_t *ch, const sfx_t *sc, int count, int sampleOffset, int bufferOffset )
|
||||
{
|
||||
int data;
|
||||
int leftvol, rightvol;
|
||||
signed short *sfx;
|
||||
int i;
|
||||
portable_samplepair_t *samp;
|
||||
static short tempMP3Buffer[PAINTBUFFER_SIZE];
|
||||
|
||||
MP3Stream_GetSamples( ch, sampleOffset, count, tempMP3Buffer, qfalse ); // qfalse = not stereo
|
||||
|
||||
leftvol = ch->leftvol*snd_vol;
|
||||
rightvol = ch->rightvol*snd_vol;
|
||||
sfx = tempMP3Buffer;
|
||||
|
||||
samp = &paintbuffer[ bufferOffset ];
|
||||
|
||||
|
||||
while ( count & 3 ) {
|
||||
data = *sfx;
|
||||
samp->left += (data * leftvol)>>8;
|
||||
samp->right += (data * rightvol)>>8;
|
||||
|
||||
sfx++;
|
||||
samp++;
|
||||
count--;
|
||||
}
|
||||
|
||||
for ( i=0 ; i<count ; i += 4 ) {
|
||||
data = sfx[i];
|
||||
samp[i].left += (data * leftvol)>>8;
|
||||
samp[i].right += (data * rightvol)>>8;
|
||||
|
||||
data = sfx[i+1];
|
||||
samp[i+1].left += (data * leftvol)>>8;
|
||||
samp[i+1].right += (data * rightvol)>>8;
|
||||
|
||||
data = sfx[i+2];
|
||||
samp[i+2].left += (data * leftvol)>>8;
|
||||
samp[i+2].right += (data * rightvol)>>8;
|
||||
|
||||
data = sfx[i+3];
|
||||
samp[i+3].left += (data * leftvol)>>8;
|
||||
samp[i+3].right += (data * rightvol)>>8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// subroutinised to save code dup (called twice) -ste
|
||||
//
|
||||
void ChannelPaint(channel_t *ch, sfx_t *sc, int count, int sampleOffset, int bufferOffset)
|
||||
{
|
||||
switch (sc->eSoundCompressionMethod)
|
||||
{
|
||||
case ct_16:
|
||||
|
||||
S_PaintChannelFrom16 (ch, sc, count, sampleOffset, bufferOffset);
|
||||
break;
|
||||
|
||||
case ct_MP3:
|
||||
|
||||
S_PaintChannelFromMP3 (ch, sc, count, sampleOffset, bufferOffset);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
assert(0); // debug aid, ignored in release. FIXME: Should we ERR_DROP here for badness-catch?
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void S_PaintChannels( int endtime ) {
|
||||
int i;
|
||||
int end;
|
||||
channel_t *ch;
|
||||
sfx_t *sc;
|
||||
int ltime, count;
|
||||
int sampleOffset;
|
||||
int normal_vol,voice_vol;
|
||||
|
||||
snd_vol = normal_vol = s_volume->value*256.0f;
|
||||
voice_vol = (s_volumeVoice->value*256.0f);
|
||||
|
||||
//Com_Printf ("%i to %i\n", s_paintedtime, endtime);
|
||||
while ( s_paintedtime < endtime ) {
|
||||
// if paintbuffer is smaller than DMA buffer
|
||||
// we may need to fill it multiple times
|
||||
end = endtime;
|
||||
if ( endtime - s_paintedtime > PAINTBUFFER_SIZE ) {
|
||||
end = s_paintedtime + PAINTBUFFER_SIZE;
|
||||
}
|
||||
|
||||
// clear the paint buffer to either music or zeros
|
||||
if ( s_rawend < s_paintedtime ) {
|
||||
if ( s_rawend ) {
|
||||
//Com_DPrintf ("background sound underrun\n");
|
||||
}
|
||||
memset(paintbuffer, 0, (end - s_paintedtime) * sizeof(portable_samplepair_t));
|
||||
} else {
|
||||
// copy from the streaming sound source
|
||||
int s;
|
||||
int stop;
|
||||
|
||||
stop = (end < s_rawend) ? end : s_rawend;
|
||||
|
||||
for ( i = s_paintedtime ; i < stop ; i++ ) {
|
||||
s = i&(MAX_RAW_SAMPLES-1);
|
||||
paintbuffer[i-s_paintedtime] = s_rawsamples[s];
|
||||
}
|
||||
// if (i != end)
|
||||
// Com_Printf ("partial stream\n");
|
||||
// else
|
||||
// Com_Printf ("full stream\n");
|
||||
for ( ; i < end ; i++ ) {
|
||||
paintbuffer[i-s_paintedtime].left =
|
||||
paintbuffer[i-s_paintedtime].right = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// paint in the channels.
|
||||
ch = s_channels;
|
||||
for ( i = 0; i < MAX_CHANNELS ; i++, ch++ ) {
|
||||
if ( !ch->thesfx || (ch->leftvol<0.25 && ch->rightvol<0.25 )) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ch->entchannel == CHAN_VOICE || ch->entchannel == CHAN_VOICE_ATTEN || ch->entchannel == CHAN_VOICE_GLOBAL )
|
||||
snd_vol = voice_vol;
|
||||
else
|
||||
snd_vol = normal_vol;
|
||||
|
||||
ltime = s_paintedtime;
|
||||
sc = ch->thesfx;
|
||||
|
||||
// we might have to make 2 passes if it is
|
||||
// a looping sound effect and the end of
|
||||
// the sameple is hit...
|
||||
//
|
||||
do
|
||||
{
|
||||
if (ch->loopSound) {
|
||||
sampleOffset = ltime % sc->iSoundLengthInSamples;
|
||||
} else {
|
||||
sampleOffset = ltime - ch->startSample;
|
||||
}
|
||||
|
||||
count = end - ltime;
|
||||
if ( sampleOffset + count > sc->iSoundLengthInSamples ) {
|
||||
count = sc->iSoundLengthInSamples - sampleOffset;
|
||||
}
|
||||
|
||||
if ( count > 0 ) {
|
||||
ChannelPaint(ch, sc, count, sampleOffset, ltime - s_paintedtime);
|
||||
ltime += count;
|
||||
}
|
||||
} while ( ltime < end && ch->loopSound );
|
||||
}
|
||||
/* temprem
|
||||
// paint in the looped channels.
|
||||
ch = loop_channels;
|
||||
for ( i = 0; i < numLoopChannels ; i++, ch++ ) {
|
||||
if ( !ch->thesfx || (!ch->leftvol && !ch->rightvol )) {
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
ltime = s_paintedtime;
|
||||
sc = ch->thesfx;
|
||||
|
||||
if (sc->soundData==NULL || sc->soundLength==0) {
|
||||
continue;
|
||||
}
|
||||
// we might have to make two passes if it
|
||||
// is a looping sound effect and the end of
|
||||
// the sample is hit
|
||||
do {
|
||||
sampleOffset = (ltime % sc->soundLength);
|
||||
|
||||
count = end - ltime;
|
||||
if ( sampleOffset + count > sc->soundLength ) {
|
||||
count = sc->soundLength - sampleOffset;
|
||||
}
|
||||
|
||||
if ( count > 0 )
|
||||
{
|
||||
ChannelPaint(ch, sc, count, sampleOffset, ltime - s_paintedtime);
|
||||
ltime += count;
|
||||
}
|
||||
|
||||
} while ( ltime < end);
|
||||
}
|
||||
}
|
||||
*/
|
||||
// transfer out according to DMA format
|
||||
S_TransferPaintBuffer( end );
|
||||
s_paintedtime = end;
|
||||
}
|
||||
}
|
||||
1155
code/client/snd_music.cpp
Normal file
1155
code/client/snd_music.cpp
Normal file
File diff suppressed because it is too large
Load Diff
67
code/client/snd_music.h
Normal file
67
code/client/snd_music.h
Normal file
@@ -0,0 +1,67 @@
|
||||
// Filename:- snd_music.h
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
|
||||
#ifndef SND_MUSIC_H
|
||||
#define SND_MUSIC_H
|
||||
|
||||
// if you change this enum, you MUST update the #defines below
|
||||
typedef enum
|
||||
{
|
||||
//( eBGRNDTRACK_DATABEGIN ) // begin-label for FOR loops
|
||||
//
|
||||
eBGRNDTRACK_EXPLORE = 0, // for normal walking around
|
||||
eBGRNDTRACK_ACTION, // for excitement
|
||||
eBGRNDTRACK_BOSS, // (optional) for final encounter
|
||||
eBGRNDTRACK_DEATH, // (optional) death "flourish"
|
||||
eBGRNDTRACK_ACTIONTRANS0, // transition from action to explore
|
||||
eBGRNDTRACK_ACTIONTRANS1, // "
|
||||
eBGRNDTRACK_ACTIONTRANS2, // "
|
||||
eBGRNDTRACK_ACTIONTRANS3, // "
|
||||
eBGRNDTRACK_EXPLORETRANS0, // transition from explore to silence
|
||||
eBGRNDTRACK_EXPLORETRANS1, // "
|
||||
eBGRNDTRACK_EXPLORETRANS2, // "
|
||||
eBGRNDTRACK_EXPLORETRANS3, // "
|
||||
//
|
||||
//( eBGRNDTRACK_DATAEND ), // tracks from this point on are for logic or copies, do NOT free them.
|
||||
//
|
||||
eBGRNDTRACK_NONDYNAMIC, // used for when music is just streaming, not part of dynamic stuff (used to be defined as same as explore entry, but this allows playing music in between 2 invokations of the same dynamic music without midleve reload, and also faster level transitioning if two consecutive dynamic sections use same DMS.DAT entries. Are you still reading this far?
|
||||
eBGRNDTRACK_SILENCE, // silence (more of a logic thing than an actual track at the moment)
|
||||
eBGRNDTRACK_FADE, // the xfade channel
|
||||
//
|
||||
eBGRNDTRACK_NUMBEROF
|
||||
|
||||
} MusicState_e;
|
||||
|
||||
#define iMAX_ACTION_TRANSITIONS 4 // these can be increased easily enough, I just need to know about them
|
||||
#define iMAX_EXPLORE_TRANSITIONS 4 //
|
||||
|
||||
#define eBGRNDTRACK_DATABEGIN eBGRNDTRACK_EXPLORE // label for FOR() loops (not in enum, else debugger shows in instead of the explore one unless I declare them backwards, which is gay)
|
||||
#define eBGRNDTRACK_DATAEND eBGRNDTRACK_NONDYNAMIC // tracks from this point on are for logic or copies, do NOT free them.
|
||||
|
||||
#define eBGRNDTRACK_FIRSTTRANSITION eBGRNDTRACK_ACTIONTRANS0 // used for "are we in transition mode" check
|
||||
#define eBGRNDTRACK_LASTTRANSITION eBGRNDTRACK_EXPLORETRANS3 //
|
||||
|
||||
|
||||
void Music_SetLevelName ( const char *psLevelName );
|
||||
qboolean Music_DynamicDataAvailable ( const char *psDynamicMusicLabel );
|
||||
const char *Music_GetFileNameForState ( MusicState_e eMusicState );
|
||||
qboolean Music_StateIsTransition ( MusicState_e eMusicState );
|
||||
qboolean Music_StateCanBeInterrupted ( MusicState_e eMusicState, MusicState_e eProposedMusicState );
|
||||
float Music_GetRandomEntryTime ( MusicState_e eMusicState );
|
||||
|
||||
#ifdef MP3STUFF_KNOWN
|
||||
qboolean Music_AllowedToTransition ( float fPlayingTimeElapsed, MusicState_e eMusicState, MusicState_e *peTransition = NULL, float *pfNewTrackEntryTime = NULL);
|
||||
#endif
|
||||
|
||||
const char *Music_BaseStateToString ( MusicState_e eMusicState, qboolean bDebugPrintQuery = qfalse);
|
||||
|
||||
|
||||
#endif // #ifndef SND_MUSIC_H
|
||||
|
||||
|
||||
//////////////// eof /////////////////
|
||||
|
||||
|
||||
59
code/client/snd_public.h
Normal file
59
code/client/snd_public.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef _SND_PUBLIC_H
|
||||
#define _SND_PUBLIC_H
|
||||
|
||||
#ifndef FINAL_BUILD
|
||||
#define PROFILE_SOUND 0
|
||||
#endif
|
||||
|
||||
void S_Init( void );
|
||||
void S_Shutdown( void );
|
||||
|
||||
// if origin is NULL, the sound will be dynamically sourced from the entity
|
||||
void S_AddAmbientLoopingSound( const vec3_t origin, unsigned char volume, sfxHandle_t sfxHandle );
|
||||
void S_StartAmbientSound( const vec3_t origin, int entityNum, unsigned char volume, sfxHandle_t sfxHandle );
|
||||
void S_StartSound( const vec3_t origin, int entnum, soundChannel_t entchannel, sfxHandle_t sfx );
|
||||
void S_StartLocalSound( sfxHandle_t sfx, int channelNum );
|
||||
void S_StartLocalLoopingSound( sfxHandle_t sfx);
|
||||
|
||||
void S_UnCacheDynamicMusic( void );
|
||||
void S_RestartMusic( void );
|
||||
void S_StartBackgroundTrack( const char *intro, const char *loop, qboolean bCalledByCGameStart );
|
||||
void S_StopBackgroundTrack( void );
|
||||
float S_GetSampleLengthInMilliSeconds( sfxHandle_t sfxHandle);
|
||||
|
||||
// cinematics and voice-over-network will send raw samples
|
||||
// 1.0 volume will be direct output of source samples
|
||||
void S_RawSamples( int samples, int rate, int width, int s_channels, const byte *data, float volume, qboolean bFirstOrOnlyUpdateThisFrame );
|
||||
// stop all sounds
|
||||
void S_StopSounds(void); // from snd_dma.cpp
|
||||
// stop all sounds and the background track
|
||||
void S_StopAllSounds( void );
|
||||
|
||||
// scan all MP3s in the sound dir and add maxvol info if necessary.
|
||||
void S_MP3_CalcVols_f( void );
|
||||
|
||||
// all continuous looping sounds must be added before calling S_Update
|
||||
void S_ClearLoopingSounds( void );
|
||||
void S_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx, soundChannel_t chan = CHAN_AUTO );
|
||||
|
||||
// recompute the reletive volumes for all running sounds
|
||||
// relative to the given entityNum / orientation
|
||||
void S_Respatialize( int entityNum, const vec3_t origin, vec3_t axis[3], qboolean inwater );
|
||||
|
||||
// let the sound system know where an entity currently is
|
||||
void S_UpdateEntityPosition( int entityNum, const vec3_t origin );
|
||||
|
||||
void S_Update( void );
|
||||
|
||||
void S_DisableSounds( void );
|
||||
|
||||
void S_BeginRegistration( void );
|
||||
|
||||
// RegisterSound will allways return a valid sample, even if it
|
||||
// has to create a placeholder. This prevents continuous filesystem
|
||||
// checks for missing files
|
||||
sfxHandle_t S_RegisterSound( const char *sample );
|
||||
|
||||
void S_FreeAllSFXMem(void);
|
||||
|
||||
#endif
|
||||
39
code/client/vmachine.cpp
Normal file
39
code/client/vmachine.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// vmachine.cpp -- wrapper to fake virtual machine for client
|
||||
|
||||
#include "vmachine.h"
|
||||
#pragma warning (disable : 4514)
|
||||
/*
|
||||
==============================================================
|
||||
|
||||
VIRTUAL MACHINE
|
||||
|
||||
==============================================================
|
||||
*/
|
||||
int VM_Call( int callnum, ... )
|
||||
{
|
||||
// assert (cgvm.entryPoint);
|
||||
|
||||
if (cgvm.entryPoint)
|
||||
{
|
||||
return cgvm.entryPoint( (&callnum)[0], (&callnum)[1], (&callnum)[2], (&callnum)[3],
|
||||
(&callnum)[4], (&callnum)[5], (&callnum)[6], (&callnum)[7],
|
||||
(&callnum)[8], (&callnum)[9] );
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
VM_DllSyscall
|
||||
|
||||
we pass this to the cgame dll to call back into the client
|
||||
============
|
||||
*/
|
||||
extern int CL_CgameSystemCalls( int *args );
|
||||
extern int CL_UISystemCalls( int *args );
|
||||
|
||||
int VM_DllSyscall( int arg, ... ) {
|
||||
// return cgvm->systemCall( &arg );
|
||||
return CL_CgameSystemCalls( &arg );
|
||||
}
|
||||
93
code/client/vmachine.h
Normal file
93
code/client/vmachine.h
Normal file
@@ -0,0 +1,93 @@
|
||||
// vmachine.h -- virtual machine header for client
|
||||
#ifndef __VMACHINE_H__
|
||||
#define __VMACHINE_H__
|
||||
|
||||
/*
|
||||
==================================================================
|
||||
|
||||
functions exported to the main executable
|
||||
|
||||
==================================================================
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
CG_INIT,
|
||||
CG_SHUTDOWN,
|
||||
CG_CONSOLE_COMMAND,
|
||||
CG_DRAW_ACTIVE_FRAME,
|
||||
CG_CROSSHAIR_PLAYER,
|
||||
CG_CAMERA_POS,
|
||||
CG_CAMERA_ANG,
|
||||
/*
|
||||
Ghoul2 Insert Start
|
||||
*/
|
||||
|
||||
CG_RESIZE_G2_BOLT,
|
||||
CG_RESIZE_G2,
|
||||
CG_RESIZE_G2_BONE,
|
||||
CG_RESIZE_G2_SURFACE,
|
||||
CG_RESIZE_G2_TEMPBONE,
|
||||
/*
|
||||
Ghoul2 Insert End
|
||||
*/
|
||||
CG_DRAW_DATAPAD_HUD,
|
||||
CG_DRAW_DATAPAD_OBJECTIVES,
|
||||
CG_DRAW_DATAPAD_WEAPONS,
|
||||
CG_DRAW_DATAPAD_INVENTORY,
|
||||
CG_DRAW_DATAPAD_FORCEPOWERS
|
||||
|
||||
} cgameExport_t;
|
||||
|
||||
/*
|
||||
==============================================================
|
||||
|
||||
VIRTUAL MACHINE
|
||||
|
||||
==============================================================
|
||||
*/
|
||||
struct vm_s {
|
||||
int (*entryPoint)( int callNum, ... );
|
||||
};
|
||||
|
||||
typedef struct vm_s vm_t;
|
||||
|
||||
extern vm_t cgvm; // interface to cgame dll or vm
|
||||
extern vm_t uivm; // interface to ui dll or vm
|
||||
|
||||
extern int VM_Call( int callnum, ... );
|
||||
extern int VM_DllSyscall( int arg, ... );
|
||||
extern void CL_ShutdownCGame(void);
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
|
||||
/*
|
||||
================
|
||||
VM_Create
|
||||
|
||||
it will attempt to load as a system dll
|
||||
================
|
||||
*/
|
||||
extern void *Sys_LoadCgame( int (**entryPoint)(int, ...), int (*systemcalls)(int, ...) );
|
||||
|
||||
inline void *VM_Create( const char *module)
|
||||
{
|
||||
void *res;
|
||||
// try to load as a system dll
|
||||
if (!Q_stricmp("cl", module))
|
||||
{
|
||||
res = Sys_LoadCgame( &cgvm.entryPoint, VM_DllSyscall );
|
||||
if ( !res)
|
||||
{
|
||||
//Com_Printf( "Failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res = 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif //__VMACHINE_H__
|
||||
Reference in New Issue
Block a user