Initial commit.
This commit is contained in:
412
codemp/client/0_sh_leak.cpp
Normal file
412
codemp/client/0_sh_leak.cpp
Normal file
@@ -0,0 +1,412 @@
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
#pragma warning( disable : 4786)
|
||||
#include "client.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include "..\smartheap\smrtheap.h"
|
||||
#if !defined(__Q_SHARED_H)
|
||||
#include "../game/q_shared.h"
|
||||
#endif
|
||||
#if !defined(_QCOMMON_H_)
|
||||
#include "../qcommon/qcommon.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#if MEM_DEBUG
|
||||
#include "..\smartheap\heapagnt.h"
|
||||
|
||||
static const int maxStack=2048;
|
||||
static int TotalMem;
|
||||
static int TotalBlocks;
|
||||
static int nStack;
|
||||
static char StackNames[maxStack][256];
|
||||
static int StackSize[maxStack];
|
||||
static int StackCount[maxStack];
|
||||
static int StackCache[48];
|
||||
static int StackCacheAt=0;
|
||||
static int CheckpointSize[1000];
|
||||
static int CheckpointCount[1000];
|
||||
|
||||
#define _FASTRPT_
|
||||
|
||||
cvar_t *mem_leakfile;
|
||||
cvar_t *mem_leakreport;
|
||||
|
||||
MEM_BOOL MEM_CALLBACK MyMemReporter2(MEM_ERROR_INFO *info)
|
||||
{
|
||||
static char buffer[10000];
|
||||
if (!info->objectCreationInfo)
|
||||
return 1;
|
||||
info=info->objectCreationInfo;
|
||||
int idx=info->checkpoint;
|
||||
if (idx<0||idx>=1000)
|
||||
{
|
||||
idx=0;
|
||||
}
|
||||
CheckpointCount[idx]++;
|
||||
CheckpointSize[idx]+=info->argSize;
|
||||
//return 1;
|
||||
dbgMemFormatCall(info,buffer,9999);
|
||||
if (strstr(buffer,"ntdll"))
|
||||
return 1;
|
||||
if (strstr(buffer,"CLBCATQ"))
|
||||
return 1;
|
||||
int i;
|
||||
TotalBlocks++;
|
||||
if (TotalBlocks%1000==0)
|
||||
{
|
||||
char mess[1000];
|
||||
sprintf(mess,"%d blocks processed\n",TotalBlocks);
|
||||
OutputDebugString(mess);
|
||||
}
|
||||
for (i=strlen(buffer);i>0;i--)
|
||||
{
|
||||
if (buffer[i]=='\n')
|
||||
break;
|
||||
}
|
||||
if (!i)
|
||||
return 1;
|
||||
buffer[i]=0;
|
||||
char *buf=buffer;
|
||||
while (*buf)
|
||||
{
|
||||
if (*buf=='\n')
|
||||
{
|
||||
buf++;
|
||||
break;
|
||||
}
|
||||
buf++;
|
||||
}
|
||||
char *start=0;
|
||||
while (*buf)
|
||||
{
|
||||
while (*buf==' ')
|
||||
buf++;
|
||||
start=buf;
|
||||
while (*buf!=0&&*buf!='\n')
|
||||
buf++;
|
||||
if (*start)
|
||||
{
|
||||
if (*buf)
|
||||
{
|
||||
*buf=0;
|
||||
buf++;
|
||||
}
|
||||
if (strlen(start)>255)
|
||||
start[255]=0;
|
||||
if (strstr(start,"std::"))
|
||||
{
|
||||
// start=0;
|
||||
continue;
|
||||
}
|
||||
if (strstr(start,"Malloc"))
|
||||
{
|
||||
start=0;
|
||||
continue;
|
||||
}
|
||||
if (strstr(start,"FS_LoadFile"))
|
||||
{
|
||||
start=0;
|
||||
continue;
|
||||
}
|
||||
if (strstr(start,"CopyString"))
|
||||
{
|
||||
start=0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!start||!*start)
|
||||
{
|
||||
start="UNKNOWN";
|
||||
}
|
||||
|
||||
for (i=0;i<48;i++)
|
||||
{
|
||||
if (StackCache[i]<0||StackCache[i]>=nStack)
|
||||
continue;
|
||||
if (!strcmpi(start,StackNames[StackCache[i]]))
|
||||
break;
|
||||
}
|
||||
if (i<48)
|
||||
{
|
||||
StackSize[StackCache[i]]+=info->argSize;
|
||||
StackCount[StackCache[i]]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0;i<nStack;i++)
|
||||
{
|
||||
if (!strcmpi(start,StackNames[i]))
|
||||
break;
|
||||
}
|
||||
if (i<nStack)
|
||||
{
|
||||
StackSize[i]+=info->argSize;
|
||||
StackCount[i]++;
|
||||
StackCache[StackCacheAt]=i;
|
||||
StackCacheAt++;
|
||||
if (StackCacheAt>=48)
|
||||
StackCacheAt=0;
|
||||
}
|
||||
else if (i<maxStack)
|
||||
{
|
||||
strcpy(StackNames[i],start);
|
||||
StackSize[i]=info->argSize;
|
||||
StackCount[i]=1;
|
||||
nStack++;
|
||||
}
|
||||
else if (nStack<maxStack)
|
||||
{
|
||||
nStack++;
|
||||
strcpy(StackNames[maxStack-1],"*****OTHER*****");
|
||||
StackSize[maxStack-1]=info->argSize;
|
||||
StackCount[maxStack-1]=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
StackSize[maxStack-1]+=info->argSize;
|
||||
StackCount[maxStack-1]++;
|
||||
}
|
||||
}
|
||||
TotalMem+=info->argSize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SH_Checking_f(void);
|
||||
#endif
|
||||
|
||||
class Leakage
|
||||
{
|
||||
MEM_POOL MyPool;
|
||||
|
||||
public:
|
||||
Leakage()
|
||||
{
|
||||
MyPool = MemInitDefaultPool();
|
||||
// MemPoolSetSmallBlockSize(MyPool, 16);
|
||||
MemPoolSetSmallBlockAllocator(MyPool,MEM_SMALL_BLOCK_SH3);
|
||||
#if MEM_DEBUG
|
||||
dbgMemSetGuardSize(2);
|
||||
#endif
|
||||
EnableChecking(100000);
|
||||
}
|
||||
|
||||
void LeakReport(void)
|
||||
{
|
||||
#if MEM_DEBUG
|
||||
|
||||
int i;
|
||||
char mess[1000];
|
||||
int blocks=dbgMemTotalCount();
|
||||
int mem=dbgMemTotalSize()/1024;
|
||||
sprintf(mess,"Final Memory Summary %d blocks %d K\n",blocks,mem);
|
||||
OutputDebugString(mess);
|
||||
for (i=0;i<1000;i++)
|
||||
{
|
||||
CheckpointSize[i]=0;
|
||||
CheckpointCount[i]=0;
|
||||
}
|
||||
|
||||
TotalMem=0;
|
||||
TotalBlocks=0;
|
||||
nStack=0;
|
||||
MemSetErrorHandler(MyMemReporter2);
|
||||
dbgMemReportLeakage(NULL,1,1000);
|
||||
MemSetErrorHandler(MemDefaultErrorHandler);
|
||||
if (TotalBlocks)
|
||||
{
|
||||
// Sort by size.
|
||||
Sleep(100);
|
||||
OutputDebugString("**************************************\n");
|
||||
OutputDebugString("**********Memory Leak Report**********\n");
|
||||
OutputDebugString("*************** By Size **************\n");
|
||||
OutputDebugString("**************************************\n");
|
||||
sprintf(mess,"Actual leakage %d blocks %d K\n",TotalBlocks,TotalMem/1024);
|
||||
OutputDebugString(mess);
|
||||
multimap<int,pair<int,char *> > sortit;
|
||||
for (i=0;i<nStack;i++)
|
||||
sortit.insert(pair<int,pair<int,char *> >(-StackSize[i],pair<int,char *>(StackCount[i],StackNames[i])));
|
||||
multimap<int,pair<int,char *> >::iterator j;
|
||||
Sleep(5);
|
||||
for (j=sortit.begin();j!=sortit.end();j++)
|
||||
{
|
||||
sprintf(mess,"%5d KB %6d cnt %s\n",-(*j).first/1024,(*j).second.first,(*j).second.second);
|
||||
// if (!(-(*j).first/1024))
|
||||
// break;
|
||||
Sleep(5);
|
||||
OutputDebugString(mess);
|
||||
}
|
||||
|
||||
// Sort by count.
|
||||
Sleep(100);
|
||||
OutputDebugString("**************************************\n");
|
||||
OutputDebugString("**********Memory Leak Report**********\n");
|
||||
OutputDebugString("************** By Count **************\n");
|
||||
OutputDebugString("**************************************\n");
|
||||
sprintf(mess,"Actual leakage %d blocks %d K\n",TotalBlocks,TotalMem/1024);
|
||||
OutputDebugString(mess);
|
||||
sortit.clear();
|
||||
for (i=0;i<nStack;i++)
|
||||
sortit.insert(pair<int,pair<int,char *> >(-StackCount[i],pair<int,char *>(StackSize[i],StackNames[i])));
|
||||
Sleep(5);
|
||||
for (j=sortit.begin();j!=sortit.end();j++)
|
||||
{
|
||||
sprintf(mess,"%5d KB %6d cnt %s\n",(*j).second.first/1024,-(*j).first,(*j).second.second);
|
||||
// if (!(-(*j).first/1024))
|
||||
// break;
|
||||
Sleep(5);
|
||||
OutputDebugString(mess);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputDebugString("No Memory Leaks\n");
|
||||
}
|
||||
|
||||
// Sort by size.
|
||||
Sleep(5);
|
||||
OutputDebugString("***************************************\n");
|
||||
OutputDebugString("By Tag, sort: size ********************\n");
|
||||
OutputDebugString("size(K) count name \n");
|
||||
OutputDebugString("-----------------------\n");
|
||||
Sleep(5);
|
||||
multimap<int,int> sorted;
|
||||
for (i=0;i<1000;i++)
|
||||
{
|
||||
if (CheckpointCount[i])
|
||||
{
|
||||
sorted.insert(pair<int,int>(-CheckpointSize[i],i));
|
||||
}
|
||||
}
|
||||
multimap<int,int>::iterator k;
|
||||
for (k=sorted.begin();k!=sorted.end();k++)
|
||||
{
|
||||
// sprintf(mess,"%8d %8d %s\n",CheckpointSize[(*k).second]/1024,CheckpointCount[(*k).second],(*k).second>=2?tagDefs[(*k).second-2]:"unknown");
|
||||
sprintf(mess,"%8d %8d %s\n",CheckpointSize[(*k).second]/1024,CheckpointCount[(*k).second],"unknown");
|
||||
Sleep(5);
|
||||
OutputDebugString(mess);
|
||||
}
|
||||
|
||||
// Sort by count.
|
||||
Sleep(5);
|
||||
OutputDebugString("***************************************\n");
|
||||
OutputDebugString("By Tag, sort: count *******************\n");
|
||||
OutputDebugString("size(K) count name \n");
|
||||
OutputDebugString("-----------------------\n");
|
||||
Sleep(5);
|
||||
sorted.clear();
|
||||
for (i=0;i<1000;i++)
|
||||
{
|
||||
if (CheckpointCount[i])
|
||||
{
|
||||
sorted.insert(pair<int,int>(-CheckpointCount[i],i));
|
||||
}
|
||||
}
|
||||
for (k=sorted.begin();k!=sorted.end();k++)
|
||||
{
|
||||
// sprintf(mess,"%8d %8d %s\n",CheckpointSize[(*k).second]/1024,CheckpointCount[(*k).second],(*k).second>=2?tagDefs[(*k).second-2]:"unknown");
|
||||
sprintf(mess,"%8d %8d %s\n",CheckpointSize[(*k).second]/1024,CheckpointCount[(*k).second],"unknown");
|
||||
Sleep(5);
|
||||
OutputDebugString(mess);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
~Leakage()
|
||||
{
|
||||
#if MEM_DEBUG
|
||||
#if 0
|
||||
if (mem_leakfile && mem_leakfile->integer)
|
||||
{
|
||||
dbgMemSetDefaultErrorOutput(DBGMEM_OUTPUT_FILE,"leakage.out");
|
||||
dbgMemReportLeakage(NULL,1,1);
|
||||
dbgMemSetDefaultErrorOutput(DBGMEM_OUTPUT_PROMPT,NULL);
|
||||
}
|
||||
#endif
|
||||
if (mem_leakreport && mem_leakreport->integer)
|
||||
{
|
||||
LeakReport();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if MEM_DEBUG
|
||||
|
||||
void EnableChecking(int x)
|
||||
{
|
||||
if (x)
|
||||
{
|
||||
dbgMemSetSafetyLevel(MEM_SAFETY_DEBUG);
|
||||
dbgMemPoolSetCheckFrequency(MyPool, x);
|
||||
dbgMemSetCheckFrequency(x);
|
||||
dbgMemDeferFreeing(TRUE);
|
||||
if (x>50000)
|
||||
{
|
||||
dbgMemSetDeferQueueLen(x+5000);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbgMemSetDeferQueueLen(50000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dbgMemSetSafetyLevel(MEM_SAFETY_SOME);
|
||||
dbgMemDeferFreeing(FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
static Leakage TheLeakage;
|
||||
|
||||
#if MEM_DEBUG
|
||||
|
||||
void MEM_Checking_f(void)
|
||||
{
|
||||
if (Cmd_Argc() != 2)
|
||||
{
|
||||
Com_Printf ("mem_checking <frequency>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (atol(Cmd_Argv(1)) > 0 && atol(Cmd_Argv(1)) < 100)
|
||||
{
|
||||
Com_Printf ("mem_checking frequency is too low ( < 100 )\n");
|
||||
return;
|
||||
}
|
||||
|
||||
TheLeakage.EnableChecking(atol(Cmd_Argv(1)));
|
||||
}
|
||||
|
||||
void MEM_Report_f(void)
|
||||
{
|
||||
TheLeakage.LeakReport();
|
||||
}
|
||||
|
||||
/*
|
||||
void myexit(void)
|
||||
{
|
||||
TheLeakage.LeakReport();
|
||||
}
|
||||
*/
|
||||
|
||||
void SH_Register(void)
|
||||
{
|
||||
Cmd_AddCommand ("mem_checking", MEM_Checking_f);
|
||||
Cmd_AddCommand ("mem_report", MEM_Report_f);
|
||||
|
||||
mem_leakfile = Cvar_Get( "mem_leakfile", "1", 0 );
|
||||
mem_leakreport = Cvar_Get( "mem_leakreport", "1", 0 );
|
||||
// atexit(myexit);
|
||||
}
|
||||
|
||||
#endif
|
||||
524
codemp/client/BinkVideo.cpp
Normal file
524
codemp/client/BinkVideo.cpp
Normal file
@@ -0,0 +1,524 @@
|
||||
#include "snd_local_console.h"
|
||||
#include "../renderer/tr_local.h"
|
||||
#include "BinkVideo.h"
|
||||
#include "RAD.h"
|
||||
|
||||
|
||||
bool bvUseGCTexMem = true;
|
||||
|
||||
#ifdef _XBOX
|
||||
int memMarker = 0;
|
||||
char* binkXboxStartAddr = NULL;
|
||||
char* binkXboxCurrentAddr = NULL;
|
||||
char* binkXboxNextAddr = NULL;
|
||||
#endif
|
||||
|
||||
static void PTR4* RADEXPLINK AllocWrapper(U32 size)
|
||||
{
|
||||
|
||||
// Give bink pre-initialized mem on xbox
|
||||
#ifdef _XBOX
|
||||
switch(memMarker)
|
||||
{
|
||||
case 0:
|
||||
memMarker++;
|
||||
binkXboxCurrentAddr = binkXboxStartAddr;
|
||||
binkXboxNextAddr = binkXboxCurrentAddr + size;
|
||||
return (void *)binkXboxStartAddr;
|
||||
case 1: case 2: case 3: case 4: case 5: case 6: case 7:
|
||||
memMarker++;
|
||||
binkXboxCurrentAddr = binkXboxNextAddr;
|
||||
binkXboxNextAddr = binkXboxCurrentAddr + size;
|
||||
return (void *)binkXboxCurrentAddr;
|
||||
case 8:
|
||||
memMarker = -1;
|
||||
binkXboxCurrentAddr = binkXboxNextAddr;
|
||||
binkXboxNextAddr = binkXboxStartAddr;
|
||||
return (void *)binkXboxCurrentAddr;
|
||||
default:
|
||||
return BinkVideo::Allocate(size);
|
||||
}
|
||||
#endif
|
||||
|
||||
return BinkVideo::Allocate(size);
|
||||
}
|
||||
|
||||
static void RADEXPLINK FreeWrapper(void PTR4* ptr)
|
||||
{
|
||||
|
||||
// Don't free the preinitialized mem
|
||||
#ifdef _XBOX
|
||||
if(memMarker < 6)
|
||||
{
|
||||
memMarker++;
|
||||
return;
|
||||
}
|
||||
else if(memMarker == 6)
|
||||
{
|
||||
memMarker = 1;
|
||||
binkXboxNextAddr = binkXboxStartAddr + XBOX_MEM_STAGE_1;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
BinkVideo::Free(ptr);
|
||||
}
|
||||
|
||||
|
||||
/*********
|
||||
BinkVideo
|
||||
*********/
|
||||
BinkVideo::BinkVideo()
|
||||
{
|
||||
bink = NULL;
|
||||
buffer = NULL;
|
||||
texture = 0;
|
||||
x1 = 0.0f;
|
||||
y1 = 0.0f;
|
||||
x2 = 0.0f;
|
||||
y2 = 0.0f;
|
||||
w = 0.0f;
|
||||
h = 0.0f;
|
||||
status = NS_BV_STOPPED;
|
||||
looping = false;
|
||||
#ifdef _XBOX
|
||||
initialized = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********
|
||||
~BinkVideo
|
||||
*********/
|
||||
BinkVideo::~BinkVideo()
|
||||
{
|
||||
Free(buffer);
|
||||
BinkClose(bink);
|
||||
}
|
||||
|
||||
/*********
|
||||
AllocateXboxMem
|
||||
Pre-Allocates memory for xbox
|
||||
*********/
|
||||
#ifdef _XBOX
|
||||
void BinkVideo::AllocateXboxMem(void)
|
||||
{
|
||||
u32 memToAllocate = XBOX_MEM_STAGE_1 +
|
||||
XBOX_MEM_STAGE_2 +
|
||||
XBOX_MEM_STAGE_3 +
|
||||
XBOX_MEM_STAGE_4 +
|
||||
XBOX_MEM_STAGE_5 +
|
||||
XBOX_MEM_STAGE_6 +
|
||||
XBOX_MEM_STAGE_7 +
|
||||
XBOX_MEM_STAGE_8 +
|
||||
XBOX_BUFFER_SIZE;
|
||||
binkXboxStartAddr = (char*)Allocate(memToAllocate);
|
||||
memMarker = 0;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/*********
|
||||
FreeXboxMem
|
||||
*********/
|
||||
void BinkVideo::FreeXboxMem(void)
|
||||
{
|
||||
initialized = false;
|
||||
Z_Free(binkXboxStartAddr);
|
||||
memMarker = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*********
|
||||
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)
|
||||
{
|
||||
|
||||
#ifdef _XBOX
|
||||
assert(initialized);
|
||||
#endif
|
||||
|
||||
// Check to see if a video is being played.
|
||||
if(status == NS_BV_PLAYING)
|
||||
{
|
||||
// stop
|
||||
this->Stop();
|
||||
}
|
||||
|
||||
// Set memory allocation wrapper
|
||||
RADSetMemory(AllocWrapper,FreeWrapper);
|
||||
|
||||
// Set up sound for consoles
|
||||
#if defined(_XBOX)
|
||||
// If 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 );
|
||||
|
||||
#elif defined(_GAMECUBE)
|
||||
BinkSoundUseNGCSound();
|
||||
|
||||
RADMEMALLOC a;
|
||||
alGeti(AL_MEMORY_ALLOCATOR, (ALint*)&a);
|
||||
|
||||
RADMEMFREE f;
|
||||
alGeti(AL_MEMORY_DEALLOCATOR, (ALint*)&f);
|
||||
|
||||
RADSetAudioMemory(a, f);
|
||||
#endif
|
||||
|
||||
|
||||
// Try to open the Bink file.
|
||||
#ifdef _XBOX
|
||||
bink = BinkOpen( filename, BINKSNDTRACK );
|
||||
if(!bink)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#elif defined _GAMECUBE
|
||||
if(bvUseGCTexMem)
|
||||
{
|
||||
extern void GLW_TexCacheLock(void);
|
||||
GLW_TexCacheLock();
|
||||
}
|
||||
|
||||
bink = BinkOpen( filename, 0);
|
||||
|
||||
if(!bink)
|
||||
{
|
||||
extern void GLW_TexCacheUnlock(void);
|
||||
GLW_TexCacheUnlock();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
assert(bink->Width <= MAX_WIDTH && bink->Height <=MAX_HEIGHT);
|
||||
|
||||
// allocate memory for the frame buffer
|
||||
#ifdef _XBOX
|
||||
buffer = AllocWrapper(XBOX_BUFFER_SIZE);
|
||||
#elif _GAMECUBE
|
||||
buffer = Allocate(XBOX_BUFFER_SIZE);
|
||||
#endif
|
||||
|
||||
// set the height, width, etc...
|
||||
x1 = xOrigin;
|
||||
y1 = yOrigin;
|
||||
x2 = x1 + width;
|
||||
y2 = y1 + height;
|
||||
w = width;
|
||||
h = height;
|
||||
|
||||
// flush any background sound reads
|
||||
#if defined (_XBOX)|| (_GAMECUBE)
|
||||
extern void S_DrainRawSoundData(void);
|
||||
S_DrainRawSoundData();
|
||||
#endif
|
||||
|
||||
// Create the video texture
|
||||
GLuint tex = (GLuint)texture;
|
||||
if (tex != 0)
|
||||
qglDeleteTextures(1, &tex);
|
||||
|
||||
qglGenTextures(1, &tex);
|
||||
qglBindTexture(GL_TEXTURE_2D, tex);
|
||||
glState.currenttextures[glState.currenttmu] = tex;
|
||||
|
||||
qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB5, bink->Width, bink->Height, 0,
|
||||
GL_RGB_SWIZZLE_EXT, GL_UNSIGNED_BYTE, buffer );
|
||||
|
||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
|
||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
|
||||
|
||||
texture = (int)tex;
|
||||
|
||||
status = NS_BV_PLAYING;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*********
|
||||
Run
|
||||
Decompresses a frame, renders it to the screen, and advances to
|
||||
the next frame.
|
||||
*********/
|
||||
bool BinkVideo::Run(void)
|
||||
{
|
||||
if(status == NS_BV_STOPPED) // A movie can't be run if it's not started first
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while(BinkWait(bink)); // Wait
|
||||
|
||||
DecompressFrame(); // Decompress
|
||||
Draw(); // Render
|
||||
|
||||
if(status != NS_BV_PAUSED) // Only advance the frame is not paused
|
||||
{
|
||||
BinkNextFrame( bink );
|
||||
}
|
||||
|
||||
|
||||
if(bink->FrameNum == (bink->Frames - 1) && !looping) // The movie is done
|
||||
{
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*********
|
||||
GetBinkData
|
||||
Returns the buffer data for the next frame of the video
|
||||
*********/
|
||||
void* BinkVideo::GetBinkData(void)
|
||||
{
|
||||
while(BinkWait(bink));
|
||||
DecompressFrame();
|
||||
BinkNextFrame(bink);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/********
|
||||
Draw
|
||||
Copies the decompressed frame to a texture to be rendered on
|
||||
the screen.
|
||||
********/
|
||||
void BinkVideo::Draw(void)
|
||||
{
|
||||
if(buffer)
|
||||
{
|
||||
qglFlush();
|
||||
|
||||
extern void RB_SetGL2D (void);
|
||||
RB_SetGL2D();
|
||||
|
||||
GL_SelectTexture(0);
|
||||
|
||||
// Update the video texture
|
||||
qglBindTexture(GL_TEXTURE_2D, (GLuint)texture);
|
||||
glState.currenttextures[glState.currenttmu] = texture;
|
||||
|
||||
qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, bink->Width, bink->Height,
|
||||
GL_RGB_SWIZZLE_EXT, GL_UNSIGNED_BYTE, buffer );
|
||||
|
||||
// Clear the screen. We use triangles here (instead
|
||||
// of glClear) because we want the back buffer to stick
|
||||
// around... so we can get a nice, cheap fade on Gamecube
|
||||
// reset.
|
||||
qglColor3f(0.f, 0.f, 0.f);
|
||||
#if defined (_XBOX) || (_GAMECUBE)
|
||||
qglBeginEXT (GL_TRIANGLE_STRIP, 4, 0, 0, 4, 0);
|
||||
#else
|
||||
qglBegin(GL_TRIANGLE_STRIP);
|
||||
#endif
|
||||
qglTexCoord2f ( 0, 0 );
|
||||
qglVertex2f (-10, -10);
|
||||
qglTexCoord2f ( 1 , 0 );
|
||||
qglVertex2f (650, -10);
|
||||
qglTexCoord2f ( 0, 1 );
|
||||
qglVertex2f (-10, 490);
|
||||
qglTexCoord2f ( 1, 1 );
|
||||
qglVertex2f (650, 490);
|
||||
qglEnd ();
|
||||
|
||||
// Draw the video
|
||||
qglColor3f(1.f, 1.f, 1.f);
|
||||
#if defined (_XBOX) || (_GAMECUBE)
|
||||
qglBeginEXT (GL_TRIANGLE_STRIP, 4, 0, 0, 4, 0);
|
||||
#else
|
||||
qglBegin(GL_TRIANGLE_STRIP);
|
||||
#endif
|
||||
qglTexCoord2f ( 0, 0 );
|
||||
qglVertex2f (x1, y1);
|
||||
qglTexCoord2f ( 1 , 0 );
|
||||
qglVertex2f (x2, y1);
|
||||
qglTexCoord2f ( 0, 1 );
|
||||
qglVertex2f (x1, y2);
|
||||
qglTexCoord2f ( 1, 1 );
|
||||
qglVertex2f (x2, y2);
|
||||
qglEnd ();
|
||||
}
|
||||
}
|
||||
|
||||
/*********
|
||||
Stop
|
||||
Stops the current movie, and clears it from memory
|
||||
*********/
|
||||
void BinkVideo::Stop(void)
|
||||
{
|
||||
BinkClose(bink);
|
||||
bink = NULL;
|
||||
#ifdef _XBOX
|
||||
FreeWrapper(buffer);
|
||||
#elif _GAMECUBE
|
||||
Free(buffer);
|
||||
#endif
|
||||
buffer = NULL;
|
||||
|
||||
GLuint tex = (GLuint)texture;
|
||||
if (tex != 0)
|
||||
qglDeleteTextures(1, &tex);
|
||||
|
||||
texture = 0;
|
||||
x1 = 0.0f;
|
||||
y1 = 0.0f;
|
||||
x2 = 0.0f;
|
||||
y2 = 0.0f;
|
||||
w = 0.0f;
|
||||
h = 0.0f;
|
||||
status = NS_BV_STOPPED;
|
||||
#ifdef _XBOX
|
||||
memMarker = 0;
|
||||
#endif
|
||||
|
||||
#ifdef _GAMECUBE
|
||||
extern void GLW_TexCacheUnlock(void);
|
||||
GLW_TexCacheUnlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********
|
||||
Pause
|
||||
Pauses the current movie. Only the current frame is rendered
|
||||
*********/
|
||||
void BinkVideo::Pause(void)
|
||||
{
|
||||
status = NS_BV_PAUSED;
|
||||
}
|
||||
|
||||
/*********
|
||||
SetExtends
|
||||
Sets dimmension variables
|
||||
*********/
|
||||
|
||||
void BinkVideo::SetExtents(float xOrigin, float yOrigin, float width, float height)
|
||||
{
|
||||
x1 = xOrigin;
|
||||
y1 = yOrigin;
|
||||
x2 = x1 + width;
|
||||
y2 = y1 + height;
|
||||
w = width;
|
||||
h = height;
|
||||
}
|
||||
|
||||
/*********
|
||||
SetMasterVolume
|
||||
Sets the volume of the specified track
|
||||
*********/
|
||||
void BinkVideo::SetMasterVolume(s32 volume)
|
||||
{
|
||||
#ifdef _XBOX
|
||||
int i;
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
BinkSetVolume(bink,i,volume);
|
||||
}
|
||||
#else
|
||||
BinkSetVolume(bink,0,volume);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********
|
||||
DecompressFrame
|
||||
Decompresses current frame and copies the data to
|
||||
the buffer
|
||||
*********/
|
||||
S32 BinkVideo::DecompressFrame()
|
||||
{
|
||||
BinkDoFrame(bink);
|
||||
|
||||
S32 skip;
|
||||
skip = BinkCopyToBuffer(
|
||||
bink,
|
||||
(void *)buffer,
|
||||
NS_BV_DEFAULT_CIN_BPS * bink->Width, //pitch
|
||||
bink->Height,
|
||||
0,
|
||||
0,
|
||||
BINKCOPYALL | BINKSURFACE565);
|
||||
return skip;
|
||||
}
|
||||
|
||||
/*********
|
||||
Allocate
|
||||
Allocates memory for the frame buffer
|
||||
*********/
|
||||
void *BinkVideo::Allocate(U32 size)
|
||||
{
|
||||
|
||||
size = RoundUp(size + 32, 32);
|
||||
char* ptr = NULL;
|
||||
|
||||
#ifdef _GAMECUBE
|
||||
if (bvUseGCTexMem)
|
||||
{
|
||||
// Try allocating from texture cache
|
||||
extern void* GLW_TexCacheAllocRaw(int size);
|
||||
ptr = (char*)GLW_TexCacheAllocRaw(size);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ptr)
|
||||
{
|
||||
// Did not allocate texture cache memory, fall
|
||||
// back to main memory..
|
||||
ptr = (char*)Z_Malloc(size, TAG_BINK, qfalse, 32);
|
||||
ptr[0] = 'z';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allocated memory from the texture cache
|
||||
ptr[0] = 't';
|
||||
}
|
||||
|
||||
return (void*)(ptr + 32);
|
||||
}
|
||||
|
||||
/*********
|
||||
FreeBuffer
|
||||
Releases the frame buffer memory
|
||||
*********/
|
||||
void BinkVideo::Free(void* ptr)
|
||||
{
|
||||
char* base = (char*)ptr - 32;
|
||||
|
||||
switch (*base)
|
||||
{
|
||||
#ifdef _GAMECUBE
|
||||
case 't':
|
||||
{
|
||||
// Free texture cache memory
|
||||
extern void GLW_TexCacheFreeRaw(void* ptr);
|
||||
GLW_TexCacheFreeRaw(base);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case 'z':
|
||||
// Free main memory
|
||||
Z_Free(base);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
73
codemp/client/BinkVideo.h
Normal file
73
codemp/client/BinkVideo.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#ifndef NS_BINKVIDEO
|
||||
#define NS_BINKVIDEO
|
||||
|
||||
#include "bink.h"
|
||||
#define NS_BV_DEFAULT_CIN_BPS (2)
|
||||
#define MAX_WIDTH 512
|
||||
#define MAX_HEIGHT 512
|
||||
|
||||
#define XBOX_MEM_STAGE_1 32640
|
||||
#define XBOX_MEM_STAGE_2 786528
|
||||
#define XBOX_MEM_STAGE_3 557152
|
||||
#define XBOX_MEM_STAGE_4 106560
|
||||
#define XBOX_MEM_STAGE_5 138304
|
||||
#define XBOX_MEM_STAGE_6 25696
|
||||
#define XBOX_MEM_STAGE_7 100
|
||||
#define XBOX_MEM_STAGE_8 100
|
||||
|
||||
#define XBOX_BUFFER_SIZE NS_BV_DEFAULT_CIN_BPS * MAX_WIDTH * MAX_HEIGHT
|
||||
|
||||
typedef enum {
|
||||
NS_BV_PLAYING, // Movie is playing
|
||||
NS_BV_STOPPED, // Movie is stopped
|
||||
NS_BV_PAUSED // Movie is paused
|
||||
};
|
||||
|
||||
class BinkVideo
|
||||
{
|
||||
private:
|
||||
HBINK bink;
|
||||
void* buffer;
|
||||
int texture;
|
||||
int status;
|
||||
bool looping;
|
||||
float x1;
|
||||
float y1;
|
||||
float x2;
|
||||
float y2;
|
||||
float w;
|
||||
float h;
|
||||
|
||||
#ifdef _XBOX
|
||||
bool initialized;
|
||||
#endif
|
||||
|
||||
void Draw(void);
|
||||
S32 DecompressFrame();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
BinkVideo();
|
||||
~BinkVideo();
|
||||
bool Start(const char *filename, float xOrigin, float yOrigin, float width, float height);
|
||||
bool Run(void);
|
||||
void Stop(void);
|
||||
void Pause(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);
|
||||
#ifdef _XBOX
|
||||
void AllocateXboxMem(void);
|
||||
void FreeXboxMem(void);
|
||||
#endif
|
||||
static void* Allocate(U32 size);
|
||||
static void Free(void* ptr);
|
||||
bool Ready(void) { return this->bink != NULL; }
|
||||
};
|
||||
|
||||
#endif
|
||||
2147
codemp/client/cl_cgame.cpp
Normal file
2147
codemp/client/cl_cgame.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1499
codemp/client/cl_cin.cpp
Normal file
1499
codemp/client/cl_cin.cpp
Normal file
File diff suppressed because it is too large
Load Diff
79
codemp/client/cl_cin_console.cpp
Normal file
79
codemp/client/cl_cin_console.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
|
||||
/*****************************************************************************
|
||||
* name: cl_cin_stubs.cpp
|
||||
*
|
||||
* desc: video and cinematic playback stubs to avoid link errors
|
||||
*
|
||||
*
|
||||
* cl_glconfig.hwtype trtypes 3dfx/ragepro need 256x256
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "client.h"
|
||||
//#include "../win32/win_local.h"
|
||||
//#include "../win32/win_input.h"
|
||||
|
||||
//#ifdef _XBOX
|
||||
//#include "../cgame/cg_local.h"
|
||||
//#include "cl_data.h"
|
||||
//#endif
|
||||
|
||||
void CIN_CloseAllVideos(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
e_status CIN_StopCinematic(int handle)
|
||||
{
|
||||
return FMV_EOF;
|
||||
}
|
||||
|
||||
e_status CIN_RunCinematic(int handle)
|
||||
{
|
||||
return FMV_EOF;
|
||||
}
|
||||
|
||||
int CIN_PlayCinematic(const char *arg0, int xpos, int ypos, int width, int height, int bits)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CIN_SetExtents(int handle, int x, int y, int w, int h)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void CIN_DrawCinematic(int handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void SCR_DrawCinematic(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void SCR_RunCinematic(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void SCR_StopCinematic(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void CIN_UploadCinematic(int handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void CIN_Init(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void CL_PlayCinematic_f(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
467
codemp/client/cl_console.cpp
Normal file
467
codemp/client/cl_console.cpp
Normal file
@@ -0,0 +1,467 @@
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
// console.c
|
||||
|
||||
#include "client.h"
|
||||
#include "../qcommon/stringed_ingame.h"
|
||||
#include "../qcommon/game_version.h"
|
||||
#include "../cgame/cg_local.h"
|
||||
#include "../client/cl_data.h"
|
||||
#include "../renderer/tr_font.h"
|
||||
|
||||
int g_console_field_width = 78;
|
||||
|
||||
console_t con;
|
||||
|
||||
cvar_t *con_conspeed;
|
||||
cvar_t *con_notifytime;
|
||||
|
||||
#define DEFAULT_CONSOLE_WIDTH 78
|
||||
|
||||
/*
|
||||
================
|
||||
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_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;
|
||||
|
||||
Com_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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifndef _XBOX // No console on Xbox
|
||||
Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
|
||||
#endif
|
||||
Cmd_AddCommand ("clear", Con_Clear_f);
|
||||
|
||||
//Initialize values on first print
|
||||
con.initialized = qfalse;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
Con_Linefeed
|
||||
===============
|
||||
*/
|
||||
static void Con_Linefeed (qboolean silent)
|
||||
{
|
||||
int i;
|
||||
|
||||
// mark time for transparent overlay
|
||||
if (con.current >= 0 && !silent )
|
||||
{
|
||||
con.times[con.current % NUM_CON_TIMES] = cls.realtime;
|
||||
}
|
||||
else
|
||||
{
|
||||
con.times[con.current % NUM_CON_TIMES] = 0;
|
||||
}
|
||||
|
||||
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( const char *txt, qboolean silent) {
|
||||
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);
|
||||
|
||||
#ifdef _XBOX
|
||||
// client to use
|
||||
if(ClientManager::splitScreenMode == qtrue) {
|
||||
y = con.current % con.totallines;
|
||||
con.text[y*con.linewidth+con.x] = (ClientManager::ActiveClientNum() << 8) | '@';
|
||||
con.x++;
|
||||
}
|
||||
#endif
|
||||
|
||||
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(silent);
|
||||
|
||||
}
|
||||
|
||||
txt++;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
Con_Linefeed (silent);
|
||||
break;
|
||||
case '\r':
|
||||
con.x = 0;
|
||||
break;
|
||||
default: // display character and advance
|
||||
y = con.current % con.totallines;
|
||||
con.text[y*con.linewidth+con.x] = (short) ((color << 8) | c);
|
||||
con.x++;
|
||||
if (con.x >= con.linewidth) {
|
||||
|
||||
Con_Linefeed(silent);
|
||||
con.x = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// mark time for transparent overlay
|
||||
|
||||
if (con.current >= 0 && !silent )
|
||||
{
|
||||
con.times[con.current % NUM_CON_TIMES] = cls.realtime;
|
||||
}
|
||||
else
|
||||
{
|
||||
con.times[con.current % NUM_CON_TIMES] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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( (int)(con.xadjust + 1 * SMALLCHAR_WIDTH), y, ']' );
|
||||
|
||||
Field_Draw( &kg.g_consoleField, (int)(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, y;
|
||||
short *text;
|
||||
int i;
|
||||
int time;
|
||||
int currentColor;
|
||||
int xStart;
|
||||
char lineBuf[256];
|
||||
int lineLen;
|
||||
|
||||
currentColor = 7;
|
||||
|
||||
#ifdef _XBOX
|
||||
int curClient = ClientManager::ActiveClientNum();
|
||||
#endif
|
||||
|
||||
// Implicitly checks for split screen mode:
|
||||
if( ClientManager::ActiveClientNum() == 1 )
|
||||
y = 250;
|
||||
else
|
||||
y = 40;
|
||||
|
||||
for ( i = con.current-NUM_CON_TIMES+1; i <= con.current; i++ )
|
||||
{
|
||||
if (/*cl->snap.ps.pm_type != PM_INTERMISSION &&*/ cls.keyCatchers & (KEYCATCH_UI | KEYCATCH_CGAME) )
|
||||
continue;
|
||||
if(cg->scoreBoardShowing)
|
||||
continue;
|
||||
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;
|
||||
|
||||
xStart = cl_conXOffset->integer + con.xadjust + 58; // Some arbitrary nonsense
|
||||
lineBuf[0] = 0;
|
||||
lineLen = 0;
|
||||
|
||||
// Scan through characters:
|
||||
for (x = 0 ; x < con.linewidth ; x++)
|
||||
{
|
||||
#ifdef _XBOX
|
||||
if(ClientManager::splitScreenMode == qtrue) {
|
||||
if ( ( ((char)text[x]) == '@') )
|
||||
{
|
||||
curClient = (text[x] >> 8)&7;
|
||||
if (curClient < 0 || curClient >= ClientManager::NumClients()) // Safety check
|
||||
curClient = 0;
|
||||
//st--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// New color:
|
||||
if ( ( (text[x]>>8)&7 ) != currentColor )
|
||||
{
|
||||
// Draw whatever we've copied thus far:
|
||||
lineBuf[lineLen] = 0;
|
||||
RE_Font_DrawString( xStart, y, lineBuf, g_color_table[currentColor], 1, -1, 1.0f );
|
||||
xStart += RE_Font_StrLenPixels( lineBuf, 1, 1.0f );
|
||||
|
||||
// Switch colors, and reset lineBuf:
|
||||
currentColor = (text[x]>>8)&7;
|
||||
lineBuf[0] = 0;
|
||||
lineLen = 0;
|
||||
}
|
||||
|
||||
// All other characters just get copied into lineBuf:
|
||||
lineBuf[lineLen++] = (text[x] & 0xFF);
|
||||
}
|
||||
|
||||
if (curClient != ClientManager::ActiveClientNum())
|
||||
continue;
|
||||
|
||||
if(ClientManager::splitScreenMode == qtrue &&
|
||||
cg->showScores == qtrue)
|
||||
continue;
|
||||
|
||||
// Draw whatever we left in lineBuf from the last iteration:
|
||||
lineBuf[lineLen] = 0;
|
||||
RE_Font_DrawString( xStart, y, lineBuf, g_color_table[currentColor], 1, -1, 1.0f );
|
||||
|
||||
y += RE_Font_HeightPixels( 1, 1.0f );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
Con_DrawConsole
|
||||
==================
|
||||
*/
|
||||
void Con_DrawConsole( void ) {
|
||||
// check for console width changes from a vid mode change
|
||||
Con_CheckResize ();
|
||||
|
||||
// Xbox - always just run in notify mode
|
||||
Con_DrawNotify();
|
||||
}
|
||||
|
||||
//================================================================
|
||||
|
||||
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 ) {
|
||||
if ( !com_cl_running->integer ) {
|
||||
return;
|
||||
}
|
||||
Field_Clear( &kg.g_consoleField );
|
||||
Con_ClearNotify ();
|
||||
cls.keyCatchers &= ~KEYCATCH_CONSOLE;
|
||||
con.finalFrac = 0; // none visible
|
||||
con.displayFrac = 0;
|
||||
}
|
||||
317
codemp/client/cl_data.cpp
Normal file
317
codemp/client/cl_data.cpp
Normal file
@@ -0,0 +1,317 @@
|
||||
#include "../cgame/cg_local.h"
|
||||
#include "cl_data.h"
|
||||
|
||||
|
||||
//tvector(ClientData*) ClientManager::clientData;
|
||||
ClientData* ClientManager::clientData[2] = { NULL };
|
||||
int ClientManager::curClient = 0;
|
||||
ClientData* ClientManager::activeClient = 0;
|
||||
int ClientManager::mainClient = 0;
|
||||
qboolean ClientManager::splitScreenMode = qfalse;
|
||||
int ClientManager::numClients = 0;
|
||||
bool ClientManager::bClOutside = false;
|
||||
|
||||
ClientData::ClientData()
|
||||
: in_mlooking(qfalse), cmd_wait(0), loopbacks(0), eventHead(0), eventTail(0), serverCommandSequence(0),
|
||||
// cg_thirdPersonSpecialCam(0), cg_thirdPerson(0), cg_thirdPersonRange(80), cg_thirdPersonAngle(0), // Pulled back for Xbox - also in cg_main
|
||||
cg_thirdPersonSpecialCam(0), cg_thirdPerson(0), cg_thirdPersonRange(90), cg_thirdPersonAngle(0),
|
||||
cg_thirdPersonPitchOffset(0), cg_thirdPersonVertOffset(16), cg_thirdPersonCameraDamp(0.3),
|
||||
cg_thirdPersonTargetDamp(0.5), cg_thirdPersonAlpha(1.0), cg_thirdPersonHorzOffset(0),
|
||||
key_overstrikeMode(qfalse), anykeydown(qfalse), cg_crossHairStatus(0), cg_autolevel(0), cg_pitch(-0.022),
|
||||
cg_sensitivity(2), cg_autoswitch(1), controller(-1), shake_intensity(0),
|
||||
shake_duration(0), shake_start(0), cg_sensitivityY(2), lastFireTime(0), cvar_modifiedFlags(0),forceConfig(0),
|
||||
modelIndex(0), forceSide(1), voiceTogglePressTime(0), swapMan1(HOTSWAP_ID_WHITE), swapMan2(HOTSWAP_ID_BLACK), myTeam(0), isSpectating(qfalse)
|
||||
|
||||
{
|
||||
state = CA_DISCONNECTED;
|
||||
// memset( &state, 0, sizeof(connstate_t));
|
||||
|
||||
memset( &mv_clc, 0, sizeof( mv_clc ) );
|
||||
m_clc = &mv_clc;
|
||||
|
||||
memset( &mv_cg , 0, sizeof( mv_cg ) );
|
||||
m_cg = &mv_cg;
|
||||
|
||||
// memset( &mv_cl, 0, sizeof( mv_cl ) );
|
||||
// m_cl = &mv_cl;
|
||||
|
||||
memset(&in_left, 0 , sizeof(kbutton_t));
|
||||
memset(&in_right, 0 , sizeof(kbutton_t));
|
||||
memset(&in_forward, 0 , sizeof(kbutton_t));
|
||||
memset(&in_back, 0 , sizeof(kbutton_t));
|
||||
|
||||
memset(&in_lookup, 0 , sizeof(kbutton_t));
|
||||
memset(&in_lookdown, 0 , sizeof(kbutton_t));
|
||||
memset(&in_moveleft, 0 , sizeof(kbutton_t));
|
||||
memset(&in_moveright, 0 , sizeof(kbutton_t));
|
||||
|
||||
memset(&in_strafe, 0 , sizeof(kbutton_t));
|
||||
memset(&in_speed, 0 , sizeof(kbutton_t));
|
||||
memset(&in_up, 0 , sizeof(kbutton_t));
|
||||
memset(&in_down, 0 , sizeof(kbutton_t));
|
||||
|
||||
memset(in_buttons, 0, sizeof(kbutton_t) * 16);
|
||||
|
||||
// Command Stuff
|
||||
memset(&cmd_text, 0, sizeof(msg_t));
|
||||
memset(cmd_text_buf, 0, sizeof(byte) *MAX_CMD_BUFFER);
|
||||
memset(cmd_defer_text_buf, 0, sizeof(char) * MAX_CMD_BUFFER);
|
||||
MSG_Init (&cmd_text, cmd_text_buf, sizeof(cmd_text_buf));
|
||||
|
||||
memset( keys, 0 , sizeof(qkey_t) *MAX_KEYS);
|
||||
|
||||
memset(eventQue, 0, sizeof(sysEvent_t) * MAX_QUED_EVENTS);
|
||||
|
||||
memset( joyInfo, 0, sizeof(JoystickInfo) * IN_MAX_JOYSTICKS);
|
||||
|
||||
strcpy(autoName, "Padawan");
|
||||
|
||||
|
||||
model[0] = 0;
|
||||
|
||||
strcpy(saber_color1, "blue");
|
||||
strcpy(saber_color2, "blue");
|
||||
|
||||
forcePowers[0] = 0;
|
||||
//forcePowersCustom[0] = 0;
|
||||
|
||||
strcpy(forcePowers, "7-1-032330000000001333");
|
||||
//strcpy(forcePowersCustom, "7-1-032330000000001333");
|
||||
|
||||
strcpy(model,"kyle/default");
|
||||
strcpy(char_color_red,"255");
|
||||
strcpy(char_color_green,"255");
|
||||
strcpy(char_color_blue,"255");
|
||||
strcpy(saber1,"single_1");
|
||||
strcpy(saber2,"none");
|
||||
strcpy(color1,"4");
|
||||
strcpy(color2,"4");
|
||||
}
|
||||
|
||||
ClientData::~ClientData()
|
||||
{
|
||||
// Really nasty hack to prevent HeapFree() being called here
|
||||
Z_PushNewDeleteTag( TAG_NEWDEL );
|
||||
|
||||
// If we got any bindings via S_Malloc, make sure to kill them here
|
||||
for( int i = 0; i < MAX_KEYS; ++i )
|
||||
if( keys[i].binding )
|
||||
Z_Free( keys[i].binding );
|
||||
|
||||
Z_PopNewDeleteTag();
|
||||
}
|
||||
|
||||
bool ClientManager::ActivateByControllerId(int id)
|
||||
{
|
||||
for (int i = 0; i < ClientManager::NumClients(); i++) {
|
||||
if (clientData[i]->controller == id) {
|
||||
ActivateClient(i);
|
||||
// SetMainClient(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void ClientManager::ClientForceInit ( int clientNum )
|
||||
{
|
||||
int oldClientNum = curClient;
|
||||
ActivateClient(clientNum);
|
||||
SetMainClient(clientNum);
|
||||
|
||||
ClientForceInit();
|
||||
|
||||
ActivateClient(oldClientNum);
|
||||
SetMainClient(oldClientNum);
|
||||
}
|
||||
|
||||
void ClientManager::ClientForceInit( void )
|
||||
{
|
||||
MSG_Init (&activeClient->cmd_text, activeClient->cmd_text_buf, sizeof(activeClient->cmd_text_buf));
|
||||
//exec control01.cfg
|
||||
if (!activeClient->loopbacks)
|
||||
{
|
||||
Z_PushNewDeleteTag( TAG_CLIENT_MANAGER );
|
||||
|
||||
activeClient->loopbacks = new loopback_t[2];
|
||||
memset(activeClient->loopbacks, 0, sizeof(loopback_t) * 2);
|
||||
|
||||
Z_PopNewDeleteTag( );
|
||||
}
|
||||
// if (!activeClient->m_cl) activeClient->m_cl = new clientActive_t;
|
||||
|
||||
// memset( activeClient->m_cl, 0, sizeof( clientActive_t ) );
|
||||
|
||||
activeClient->state = CA_DISCONNECTED; // no longer CA_UNINITIALIZED
|
||||
|
||||
Cbuf_ExecuteText( EXEC_APPEND, "exec control01.cfg\n" );
|
||||
|
||||
}
|
||||
|
||||
extern void IN_KeyUp( kbutton_t *b );
|
||||
void ClientManager::ClearAllClientInputs(void)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
for ( i = 0 ; i < numClients; i++)
|
||||
{
|
||||
for ( j = 0 ; j < 16; j++)
|
||||
{
|
||||
if (clientData[i]->in_buttons[j].active)
|
||||
{
|
||||
// IN_KeyUp(&clientData[i]->in_buttons[j]);
|
||||
clientData[i]->in_buttons[j].down[0] = clientData[i]->in_buttons[j].down[1] = 0;
|
||||
clientData[i]->in_buttons[j].active = qfalse;
|
||||
}
|
||||
}
|
||||
if ( clientData[i]->in_down.active)
|
||||
{
|
||||
// IN_KeyUp(&clientData[i]->in_down);
|
||||
clientData[i]->in_down.down[0] = clientData[i]->in_down.down[1] = 0;
|
||||
clientData[i]->in_down.active = qfalse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientManager::ClientForceAllInit( void )
|
||||
{
|
||||
for (int i = 0; i < numClients; i++) {
|
||||
ClientForceInit(i);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientManager::Init(int _numClients)
|
||||
{
|
||||
Shutdown();
|
||||
|
||||
Z_PushNewDeleteTag( TAG_CLIENT_MANAGER );
|
||||
|
||||
numClients = _numClients;
|
||||
for (int i = 0; i < _numClients; i++)
|
||||
{
|
||||
clientData[i] = new ClientData();
|
||||
clientData[i]->m_cl = new clientActive_t;
|
||||
memset( clientData[i]->m_cl, 0, sizeof(clientActive_t) );
|
||||
}
|
||||
|
||||
ActivateClient(0);
|
||||
|
||||
mainClient = 0;
|
||||
|
||||
Z_PopNewDeleteTag();
|
||||
}
|
||||
|
||||
void ClientManager::Shutdown( void )
|
||||
{
|
||||
// tvector(ClientData*)::iterator begin = clientData.begin(), end = clientData.end();
|
||||
for ( int i = 0; i < numClients; ++i )
|
||||
delete clientData[i];
|
||||
// clientData.clear();
|
||||
numClients = 0;
|
||||
curClient = 0;
|
||||
activeClient = 0;
|
||||
}
|
||||
|
||||
void ClientManager::Resize( int n )
|
||||
{
|
||||
Z_PushNewDeleteTag( TAG_CLIENT_MANAGER );
|
||||
|
||||
if (n < numClients )
|
||||
{
|
||||
for (int i = n; i < numClients; i++)
|
||||
{
|
||||
if (clientData[i]->loopbacks)
|
||||
delete clientData[i]->loopbacks;
|
||||
// if (clientData[i]->m_cl) delete clientData[i]->m_cl;
|
||||
|
||||
Z_PushNewDeleteTag( TAG_CLIENT_MANAGER_SPECIAL );
|
||||
delete clientData[n]->m_cl;
|
||||
delete clientData[n];
|
||||
Z_PopNewDeleteTag( );
|
||||
}
|
||||
// clientData.resize(n);
|
||||
numClients = n;
|
||||
}
|
||||
else if (n > numClients )
|
||||
{
|
||||
for( int i = numClients; i < n; ++i )
|
||||
{
|
||||
clientData[i] = new ClientData();
|
||||
clientData[i]->m_cl = new clientActive_t;
|
||||
memset( clientData[i]->m_cl, 0, sizeof(clientActive_t) );
|
||||
}
|
||||
numClients = n;
|
||||
// int diff = n - numClients;
|
||||
// clientData.reserve(diff);
|
||||
// for ( ; diff > 0; diff--)
|
||||
// clientData.push_back(new ClientData());
|
||||
}
|
||||
|
||||
Z_PopNewDeleteTag( );
|
||||
}
|
||||
|
||||
int ClientManager::AddClient( void )
|
||||
{
|
||||
// Special tag that tells Z_Malloc to use HeapAlloc() instead - and thus
|
||||
// use the same memory as ModelMem.
|
||||
Z_PushNewDeleteTag( TAG_CLIENT_MANAGER_SPECIAL ); //TAG_CLIENT_MANAGER );
|
||||
|
||||
// clientData.push_back(new ClientData());
|
||||
// return static_cast<int>(clientData.size()) - 1;
|
||||
clientData[numClients] = new ClientData();
|
||||
clientData[numClients]->m_cl = new clientActive_t;
|
||||
memset( clientData[numClients]->m_cl, 0, sizeof(clientActive_t) );
|
||||
clientData[numClients]->m_cg->widescreen = cg->widescreen;
|
||||
numClients++;
|
||||
|
||||
Z_PopNewDeleteTag( );
|
||||
|
||||
return numClients - 1;
|
||||
}
|
||||
|
||||
bool ClientManager::IsAClientControlller ( int id )
|
||||
{
|
||||
for (int i = 0; i < ClientManager::NumClients(); i++) {
|
||||
if (clientData[i]->controller == id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClientManager::ClientFeedDeferedScript(void )
|
||||
{
|
||||
if ( *(activeClient->cmd_defer_text_buf) != 0)
|
||||
{
|
||||
Cbuf_AddText( activeClient->cmd_defer_text_buf );
|
||||
*(activeClient->cmd_defer_text_buf) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ClientManager::ClientActiveRelocate( bool bOutside )
|
||||
{
|
||||
if( bOutside == bClOutside )
|
||||
return;
|
||||
|
||||
Z_PushNewDeleteTag( bOutside ? TAG_CLIENT_MANAGER_SPECIAL : TAG_CLIENT_MANAGER );
|
||||
clientActive_t *newCl = new clientActive_t;
|
||||
Z_PopNewDeleteTag();
|
||||
|
||||
memcpy( newCl, clientData[0]->m_cl, sizeof(clientActive_t) );
|
||||
memset( clientData[0]->m_cl, 0, sizeof(clientActive_t) );
|
||||
|
||||
Z_PushNewDeleteTag( !bOutside ? TAG_CLIENT_MANAGER_SPECIAL : TAG_CLIENT_MANAGER );
|
||||
delete clientData[0]->m_cl;
|
||||
Z_PopNewDeleteTag();
|
||||
|
||||
clientData[0]->m_cl = newCl;
|
||||
bClOutside = bOutside;
|
||||
if( curClient == 0 )
|
||||
cl = newCl;
|
||||
}
|
||||
|
||||
// Hacky function for server code that can't seem to include cl_data properly:
|
||||
bool SplitScreenModeActive( void )
|
||||
{
|
||||
return ClientManager::splitScreenMode;
|
||||
}
|
||||
272
codemp/client/cl_data.h
Normal file
272
codemp/client/cl_data.h
Normal file
@@ -0,0 +1,272 @@
|
||||
#ifndef _CL_DATA_H_
|
||||
#define _CL_DATA_H_
|
||||
|
||||
//#include "../cgame/cg_local.h"
|
||||
//#include "../game/g_shared.h"
|
||||
//#include "../game/g_local.h"
|
||||
#include "client.h"
|
||||
#include "cl_input_hotswap.h"
|
||||
|
||||
#include "../win32/win_input.h"
|
||||
|
||||
#include <vector>
|
||||
#define MAX_CMD_BUFFER 4096
|
||||
#define MAX_LOOPBACK 16
|
||||
|
||||
#define MAX_QUED_EVENTS 256
|
||||
#define MASK_QUED_EVENTS ( MAX_QUED_EVENTS - 1 )
|
||||
#define STRING_SIZE 64
|
||||
|
||||
|
||||
typedef struct {
|
||||
byte data[1359];
|
||||
int datalen;
|
||||
} loopmsg_t;
|
||||
|
||||
typedef struct {
|
||||
loopmsg_t msgs[MAX_LOOPBACK];
|
||||
int get, send;
|
||||
} loopback_t;
|
||||
|
||||
#define CM_START_LOOP() ClientManager::StartIt(); do {
|
||||
#define CM_END_LOOP() } while (ClientManager::NextIt());
|
||||
|
||||
|
||||
#define IN_MAX_JOYSTICKS 2
|
||||
|
||||
class ClientData
|
||||
{
|
||||
public:
|
||||
ClientData();
|
||||
~ClientData();
|
||||
|
||||
public:
|
||||
connstate_t state; // connection status
|
||||
|
||||
// clientActive_t mv_cl;
|
||||
clientActive_t* m_cl;
|
||||
|
||||
clientConnection_t mv_clc;
|
||||
clientConnection_t *m_clc;
|
||||
|
||||
cg_t mv_cg;
|
||||
cg_t *m_cg;
|
||||
|
||||
// Button Data
|
||||
kbutton_t in_left, in_right, in_forward, in_back;
|
||||
kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright;
|
||||
kbutton_t in_strafe, in_speed;
|
||||
kbutton_t in_up, in_down;
|
||||
kbutton_t in_buttons[16];
|
||||
qboolean in_mlooking;
|
||||
|
||||
// Hot-swap button data
|
||||
HotSwapManager swapMan1;
|
||||
HotSwapManager swapMan2;
|
||||
|
||||
// Command Text Data
|
||||
int cmd_wait;
|
||||
msg_t cmd_text;
|
||||
byte cmd_text_buf[MAX_CMD_BUFFER];
|
||||
char cmd_defer_text_buf[MAX_CMD_BUFFER];
|
||||
|
||||
// NET stuff
|
||||
loopback_t *loopbacks;
|
||||
|
||||
// event stuff
|
||||
sysEvent_t eventQue[MAX_QUED_EVENTS];
|
||||
int eventHead, eventTail;
|
||||
|
||||
// key stuff
|
||||
qboolean key_overstrikeMode;
|
||||
qboolean anykeydown;
|
||||
qkey_t keys[MAX_KEYS];
|
||||
|
||||
// Used for autolevel
|
||||
unsigned long lastFireTime;
|
||||
// Used for taunting
|
||||
unsigned long voiceTogglePressTime;
|
||||
|
||||
// controller stuff
|
||||
int controller;
|
||||
|
||||
JoystickInfo joyInfo[IN_MAX_JOYSTICKS];
|
||||
|
||||
int serverCommandSequence;
|
||||
|
||||
int cg_thirdPersonSpecialCam;
|
||||
|
||||
int cg_thirdPerson;
|
||||
int cg_thirdPersonRange;
|
||||
int cg_thirdPersonAngle;
|
||||
int cg_thirdPersonPitchOffset;
|
||||
int cg_thirdPersonVertOffset;
|
||||
float cg_thirdPersonCameraDamp;
|
||||
float cg_thirdPersonTargetDamp;
|
||||
|
||||
float cg_thirdPersonAlpha;
|
||||
int cg_thirdPersonHorzOffset;
|
||||
|
||||
vec3_t cameraFocusAngles, cameraFocusLoc;
|
||||
vec3_t cameraIdealTarget, cameraIdealLoc;
|
||||
vec3_t cameraCurTarget, cameraCurLoc;
|
||||
int cameraLastFrame;
|
||||
|
||||
float cameraLastYaw;
|
||||
float cameraStiffFactor;
|
||||
|
||||
int cg_crossHairStatus;
|
||||
|
||||
short cg_autolevel;
|
||||
float cg_pitch;
|
||||
float cg_sensitivity;
|
||||
#ifdef _XBOX
|
||||
float cg_sensitivityY;
|
||||
#endif
|
||||
short cg_autoswitch;
|
||||
|
||||
int cvar_modifiedFlags;
|
||||
|
||||
char autoName[STRING_SIZE];
|
||||
|
||||
//character Model and saber info
|
||||
char model[STRING_SIZE];
|
||||
int modelIndex;
|
||||
//colors
|
||||
char char_color_red[STRING_SIZE];
|
||||
char char_color_green[STRING_SIZE];
|
||||
char char_color_blue[STRING_SIZE];
|
||||
|
||||
char saber1[STRING_SIZE];
|
||||
char saber2[STRING_SIZE];
|
||||
char color1[STRING_SIZE];
|
||||
char color2[STRING_SIZE];
|
||||
char saber_color1[STRING_SIZE];
|
||||
char saber_color2[STRING_SIZE];
|
||||
char forcePowers[STRING_SIZE];
|
||||
// char forcePowersCustom[STRING_SIZE];
|
||||
int forceSide;
|
||||
int forceConfig;
|
||||
int myTeam;
|
||||
qboolean isSpectating;
|
||||
|
||||
|
||||
// char profileName[STRING_SIZE];
|
||||
|
||||
|
||||
|
||||
// Camera shake stuff
|
||||
float shake_intensity;
|
||||
int shake_duration;
|
||||
int shake_start;
|
||||
|
||||
int cgRageTime;
|
||||
int cgRageFadeTime;
|
||||
float cgRageFadeVal;
|
||||
|
||||
int cgRageRecTime;
|
||||
int cgRageRecFadeTime;
|
||||
float cgRageRecFadeVal;
|
||||
|
||||
int cgAbsorbTime;
|
||||
int cgAbsorbFadeTime;
|
||||
float cgAbsorbFadeVal;
|
||||
|
||||
int cgProtectTime;
|
||||
int cgProtectFadeTime;
|
||||
float cgProtectFadeVal;
|
||||
|
||||
int cgYsalTime;
|
||||
int cgYsalFadeTime;
|
||||
float cgYsalFadeVal;
|
||||
};
|
||||
|
||||
|
||||
class ClientManager
|
||||
{
|
||||
public:
|
||||
|
||||
__inline static void StartIt( void ) { ActivateClient(0); }
|
||||
__inline static bool NextIt( void )
|
||||
{
|
||||
// if ( curClient + 1 >= static_cast<int>(clientData.size()) ) {
|
||||
if ( curClient + 1 >= numClients ) {
|
||||
ActivateClient(mainClient);
|
||||
return false;
|
||||
}
|
||||
ActivateClient( curClient + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
__inline static int ActiveController( void ) { return activeClient->controller; }
|
||||
|
||||
__inline static void SetActiveController( int ctl ) { activeClient->controller = ctl; }
|
||||
__inline static void SetMainClient( int client) { mainClient = client; }
|
||||
__inline static void ActivateMainClient( void ) { ActivateClient(mainClient); }
|
||||
__inline static ClientData& ActiveClient( void ) { return *activeClient; }
|
||||
__inline static ClientData& GetClient( int i ) { return *clientData[i] ; }
|
||||
__inline static int ActiveClientNum( void ) { return curClient; }
|
||||
__inline static int ActivePort ( void ) { return Cvar_VariableIntegerValue("qport") + curClient; }
|
||||
|
||||
__inline static bool IsActiveClient (int n) { return (n == curClient); }
|
||||
__inline static int NumClients( void ) { return numClients; }
|
||||
|
||||
__inline static int Controller(int clientNum) { return clientData[clientNum]->controller; }
|
||||
__inline static void ActivateClient( int client )
|
||||
{
|
||||
if (client >= numClients) return;
|
||||
|
||||
// clientData[curClient]->m_cg = cg;
|
||||
// if(clientData[curClient]->m_cl)
|
||||
// clientData[curClient]->m_cl = cl;
|
||||
// clientData[curClient]->m_clc = clc;
|
||||
// Need to check when removing second client:
|
||||
if( curClient < numClients )
|
||||
clientData[curClient]->state = cls.state;
|
||||
|
||||
curClient = client;
|
||||
activeClient = clientData[curClient];
|
||||
|
||||
cg = clientData[curClient]->m_cg;
|
||||
// if(clientData[curClient]->m_cl)
|
||||
cl = clientData[curClient]->m_cl;
|
||||
clc = clientData[curClient]->m_clc;
|
||||
cls.state = clientData[curClient]->state;
|
||||
}
|
||||
|
||||
static int AddClient( void );
|
||||
static void Resize( int n );
|
||||
static void Shutdown( void );
|
||||
static void Init( int _numClients );
|
||||
|
||||
static void ClientForceInit (int client);
|
||||
static void ClientForceInit ( void );
|
||||
static void ClearAllClientInputs(void);
|
||||
static void ClientForceAllInit ( void );
|
||||
|
||||
static bool ActivateByControllerId( int id);
|
||||
static bool IsAClientControlller ( int id );
|
||||
static void ClientFeedDeferedScript(void );
|
||||
|
||||
static void ClientActiveRelocate( bool bOutside );
|
||||
|
||||
private:
|
||||
ClientManager() {}
|
||||
~ClientManager() {}
|
||||
operator =(const ClientManager&);
|
||||
|
||||
private:
|
||||
// static tvector(ClientData*) clientData;
|
||||
static ClientData* clientData[2];
|
||||
static int curClient;
|
||||
static int mainClient;
|
||||
static ClientData* activeClient;
|
||||
static int numClients;
|
||||
|
||||
static bool bClOutside;
|
||||
|
||||
public:
|
||||
static qboolean splitScreenMode;
|
||||
};
|
||||
|
||||
#endif
|
||||
2757
codemp/client/cl_input.cpp
Normal file
2757
codemp/client/cl_input.cpp
Normal file
File diff suppressed because it is too large
Load Diff
258
codemp/client/cl_input_hotswap.cpp
Normal file
258
codemp/client/cl_input_hotswap.cpp
Normal file
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
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 "cl_data.h"
|
||||
#include "../qcommon/xb_settings.h"
|
||||
|
||||
#define FORCESELECTTIME forceSelectTime
|
||||
#define FORCESELECT forceSelect
|
||||
#define INVSELECTTIME invenSelectTime
|
||||
#define INVSELECT itemSelect
|
||||
#define REGISTERSOUND S_RegisterSound
|
||||
#define STARTSOUND S_StartLocalSound
|
||||
#define WEAPONBINDSTR "weaponclean"
|
||||
|
||||
#define BIND_TIME 2000 //number of milliseconds button is held before binding
|
||||
#define EXEC_TIME 500 //max ms button can be held to execute in bind mode
|
||||
|
||||
|
||||
const char *itemCommands[HI_NUM_HOLDABLE] = {
|
||||
NULL, //HI_NONE
|
||||
"use_seeker\n",
|
||||
"use_field\n",
|
||||
"use_bacta\n",
|
||||
"use_bactabig\n",
|
||||
"use_electrobinoculars\n",
|
||||
"use_sentry\n",
|
||||
"use_jetpack\n",
|
||||
NULL, //ammo dispenser
|
||||
NULL, //health dispenser
|
||||
"use_eweb\n",
|
||||
"use_cloak\n",
|
||||
};
|
||||
|
||||
// Commands to issue when user presses a force-bound button
|
||||
const char *forceDownCommands[NUM_FORCE_POWERS] = {
|
||||
"force_heal\n", // FP_HEAL
|
||||
NULL, // FP_LEVITATION
|
||||
"force_speed\n", // FP_SPEED
|
||||
"force_throw\n", // FP_PUSH
|
||||
"force_pull\n", // FP_PULL
|
||||
"force_distract\n", // FP_TELEPATHY
|
||||
"+force_grip\n", // FP_GRIP
|
||||
"+force_lightning\n", // FP_LIGHTNING
|
||||
"force_rage\n", // FP_RAGE
|
||||
"force_protect\n", // FP_PROTECT
|
||||
"force_absorb\n", // FP_ABSORB
|
||||
"force_healother\n", // FP_TEAM_HEAL
|
||||
"force_forcepowerother\n", // FP_TEAM_FORCE
|
||||
"+force_drain\n", // FP_DRAIN
|
||||
"force_seeing\n", // FP_SEE
|
||||
NULL, // FP_SABER_OFFENSE
|
||||
NULL, // FP_SABER_DEFENSE
|
||||
NULL, // FP_SABERTHROW
|
||||
};
|
||||
|
||||
// Commands to issue when user releases a force-bound button
|
||||
const char *forceUpCommands[NUM_FORCE_POWERS] = {
|
||||
NULL, // FP_HEAL
|
||||
NULL, // FP_LEVITATION
|
||||
NULL, // FP_SPEED
|
||||
NULL, // FP_PUSH
|
||||
NULL, // FP_PULL
|
||||
NULL, // FP_TELEPATHY
|
||||
"-force_grip\n", // FP_GRIP
|
||||
"-force_lightning\n", // FP_LIGHTNING
|
||||
NULL, // FP_RAGE
|
||||
NULL, // FP_PROTECT
|
||||
NULL, // FP_ABSORB
|
||||
NULL, // FP_TEAM_HEAL
|
||||
NULL, // FP_TEAM_FORCE
|
||||
"-force_drain\n", // FP_DRAIN
|
||||
NULL, // FP_SEE
|
||||
NULL, // FP_SABER_OFFENSE
|
||||
NULL, // FP_SABER_DEFENSE
|
||||
NULL, // FP_SABERTHROW
|
||||
};
|
||||
|
||||
|
||||
HotSwapManager::HotSwapManager(int uniqueID) :
|
||||
uniqueID(uniqueID)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
||||
const char *HotSwapManager::GetBinding(void)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
// Need to use unique variables for each client in split screen:
|
||||
sprintf(buf, "hotswap%d", uniqueID+(ClientManager::ActiveClientNum()*4));
|
||||
cvar_t *cvar = Cvar_Get(buf, "", CVAR_ARCHIVE);
|
||||
|
||||
if(!cvar || !cvar->string[0])
|
||||
return NULL;
|
||||
|
||||
if (cvar->integer < HOTSWAP_CAT_ITEM) { // Weapon
|
||||
return va("weaponclean %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+(ClientManager::ActiveClientNum()*4));
|
||||
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_APPEND, binding);
|
||||
}
|
||||
}
|
||||
|
||||
void HotSwapManager::ExecuteUp(void)
|
||||
{
|
||||
const char *binding = GetBindingUp();
|
||||
if(binding) {
|
||||
Cbuf_ExecuteText(EXEC_APPEND, 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() || noBind) {
|
||||
ExecuteUp();
|
||||
}
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
||||
void HotSwapManager::Reset(void)
|
||||
{
|
||||
down = false;
|
||||
bindTime = 0;
|
||||
noBind = false;
|
||||
}
|
||||
|
||||
void HotSwapBind(int buttonID, int category, int value)
|
||||
{
|
||||
char buf[64];
|
||||
sprintf(buf, "hotswap%d", buttonID+(ClientManager::ActiveClientNum()*4));
|
||||
|
||||
// Add category as an offset for when we retrieve it
|
||||
Cvar_SetValue( buf, value+category );
|
||||
Settings.hotswapMP[buttonID+(ClientManager::ActiveClientNum()*2)] = value+category;
|
||||
|
||||
Settings.Save();
|
||||
}
|
||||
|
||||
63
codemp/client/cl_input_hotswap.h
Normal file
63
codemp/client/cl_input_hotswap.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef __CL_INPUT_HOTSWAP_H
|
||||
#define __CL_INPUT_HOTSWAP_H
|
||||
|
||||
|
||||
#define HOTSWAP_ID_WHITE 0
|
||||
#define HOTSWAP_ID_BLACK 1
|
||||
|
||||
#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
|
||||
1738
codemp/client/cl_keys.cpp
Normal file
1738
codemp/client/cl_keys.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2337
codemp/client/cl_main.cpp
Normal file
2337
codemp/client/cl_main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
179
codemp/client/cl_net_chan.cpp
Normal file
179
codemp/client/cl_net_chan.cpp
Normal file
@@ -0,0 +1,179 @@
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
#include "client.h"
|
||||
|
||||
// TTimo: unused, commenting out to make gcc happy
|
||||
#if 1
|
||||
/*
|
||||
==============
|
||||
CL_Netchan_Encode
|
||||
|
||||
// first 12 bytes of the data are always:
|
||||
long serverId;
|
||||
long messageAcknowledge;
|
||||
long reliableAcknowledge;
|
||||
|
||||
==============
|
||||
*/
|
||||
static void CL_Netchan_Encode( msg_t *msg ) {
|
||||
#ifdef _XBOX
|
||||
return;
|
||||
#endif
|
||||
int serverId, messageAcknowledge, reliableAcknowledge;
|
||||
int i, index, srdc, sbit, soob;
|
||||
byte key, *string;
|
||||
|
||||
if ( msg->cursize <= CL_ENCODE_START ) {
|
||||
return;
|
||||
}
|
||||
|
||||
srdc = msg->readcount;
|
||||
sbit = msg->bit;
|
||||
soob = msg->oob;
|
||||
|
||||
msg->bit = 0;
|
||||
msg->readcount = 0;
|
||||
msg->oob = (qboolean)0;
|
||||
|
||||
serverId = MSG_ReadLong(msg);
|
||||
messageAcknowledge = MSG_ReadLong(msg);
|
||||
reliableAcknowledge = MSG_ReadLong(msg);
|
||||
|
||||
msg->oob = (qboolean)soob;
|
||||
msg->bit = sbit;
|
||||
msg->readcount = srdc;
|
||||
|
||||
string = (byte *)clc->serverCommands[ reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ];
|
||||
index = 0;
|
||||
//
|
||||
key = clc->challenge ^ serverId ^ messageAcknowledge;
|
||||
for (i = CL_ENCODE_START; i < msg->cursize; i++) {
|
||||
// modify the key with the last received now acknowledged server command
|
||||
if (!string[index])
|
||||
index = 0;
|
||||
if (/*string[index] > 127 || */ // eurofix: remove this so we can chat in european languages... -ste
|
||||
string[index] == '%')
|
||||
{
|
||||
key ^= '.' << (i & 1);
|
||||
}
|
||||
else {
|
||||
key ^= string[index] << (i & 1);
|
||||
}
|
||||
index++;
|
||||
// encode the data with this key
|
||||
*(msg->data + i) = (*(msg->data + i)) ^ key;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
CL_Netchan_Decode
|
||||
|
||||
// first four bytes of the data are always:
|
||||
long reliableAcknowledge;
|
||||
|
||||
==============
|
||||
*/
|
||||
static void CL_Netchan_Decode( msg_t *msg ) {
|
||||
#ifdef _XBOX
|
||||
return;
|
||||
#endif
|
||||
long reliableAcknowledge, i, index;
|
||||
byte key, *string;
|
||||
int srdc, sbit, soob;
|
||||
|
||||
srdc = msg->readcount;
|
||||
sbit = msg->bit;
|
||||
soob = msg->oob;
|
||||
|
||||
msg->oob = (qboolean)0;
|
||||
|
||||
reliableAcknowledge = MSG_ReadLong(msg);
|
||||
|
||||
msg->oob = (qboolean)soob;
|
||||
msg->bit = sbit;
|
||||
msg->readcount = srdc;
|
||||
|
||||
string = (unsigned char *)clc->reliableCommands[ reliableAcknowledge & (MAX_RELIABLE_COMMANDS-1) ];
|
||||
index = 0;
|
||||
// xor the client challenge with the netchan sequence number (need something that changes every message)
|
||||
key = clc->challenge ^ LittleLong( *(unsigned *)msg->data );
|
||||
for (i = msg->readcount + CL_DECODE_START; i < msg->cursize; i++) {
|
||||
// modify the key with the last sent and with this message acknowledged client command
|
||||
if (!string[index])
|
||||
index = 0;
|
||||
if (/*string[index] > 127 || */ // eurofix: remove this so we can chat in european languages... -ste
|
||||
string[index] == '%')
|
||||
{
|
||||
key ^= '.' << (i & 1);
|
||||
}
|
||||
else {
|
||||
key ^= string[index] << (i & 1);
|
||||
}
|
||||
index++;
|
||||
// decode the data with this key
|
||||
*(msg->data + i) = *(msg->data + i) ^ key;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_Netchan_TransmitNextFragment
|
||||
=================
|
||||
*/
|
||||
void CL_Netchan_TransmitNextFragment( netchan_t *chan ) {
|
||||
Netchan_TransmitNextFragment( chan );
|
||||
}
|
||||
|
||||
//byte chksum[65536];
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_Netchan_Transmit
|
||||
================
|
||||
*/
|
||||
void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg )
|
||||
{
|
||||
MSG_WriteByte( msg, clc_EOF );
|
||||
|
||||
CL_Netchan_Encode( msg );
|
||||
if( !Netchan_Transmit( chan, msg->cursize, msg->data ) )
|
||||
{
|
||||
// Don't call Com_Error if we're already disconnecting!
|
||||
if( com_errorEntered )
|
||||
return;
|
||||
|
||||
// Quickly detect dead connections: (may want to put in some relaxation here?)
|
||||
Com_Error( ERR_DROP, "@MENUS_LOST_CONNECTION" );
|
||||
}
|
||||
}
|
||||
|
||||
extern int oldsize;
|
||||
int newsize = 0;
|
||||
|
||||
/*
|
||||
=================
|
||||
CL_Netchan_Process
|
||||
=================
|
||||
*/
|
||||
qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) {
|
||||
int ret;
|
||||
// int i;
|
||||
// static int newsize = 0;
|
||||
|
||||
ret = Netchan_Process( chan, msg );
|
||||
if (!ret)
|
||||
return qfalse;
|
||||
CL_Netchan_Decode( msg );
|
||||
// Huff_Decompress( msg, CL_DECODE_START );
|
||||
// for(i=CL_DECODE_START+msg->readcount;i<msg->cursize;i++) {
|
||||
// if (msg->data[i] != chksum[i-(CL_DECODE_START+msg->readcount)]) {
|
||||
// Com_Error(ERR_DROP,"bad %d v %d\n", msg->data[i], chksum[i-(CL_DECODE_START+msg->readcount)]);
|
||||
// }
|
||||
// }
|
||||
newsize += msg->cursize;
|
||||
// Com_Printf("saved %d to %d (%d%%)\n", (oldsize>>3), newsize, 100-(newsize*100/(oldsize>>3)));
|
||||
return qtrue;
|
||||
}
|
||||
1064
codemp/client/cl_parse.cpp
Normal file
1064
codemp/client/cl_parse.cpp
Normal file
File diff suppressed because it is too large
Load Diff
486
codemp/client/cl_scrn.cpp
Normal file
486
codemp/client/cl_scrn.cpp
Normal file
@@ -0,0 +1,486 @@
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
// cl_scrn.c -- master for refresh, status bar, console, chat, notify, etc
|
||||
|
||||
#include "client.h"
|
||||
|
||||
#ifdef _XBOX
|
||||
#include "../cgame/cg_local.h"
|
||||
#include "cl_data.h"
|
||||
#endif
|
||||
|
||||
#include "../xbox/XBVoice.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;
|
||||
#ifndef FINAL_BUILD
|
||||
cvar_t *cl_debugVoice;
|
||||
#endif
|
||||
|
||||
/*
|
||||
================
|
||||
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
|
||||
=================
|
||||
*/
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===============================================================================
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
DEBUG GRAPH
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
#ifndef _XBOX
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float value;
|
||||
int color;
|
||||
} graphsamp_t;
|
||||
|
||||
static int current;
|
||||
static graphsamp_t values[1024];
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
==============
|
||||
SCR_DebugGraph
|
||||
==============
|
||||
*/
|
||||
void SCR_DebugGraph (float value, int color)
|
||||
{
|
||||
#ifndef _XBOX
|
||||
values[current&1023].value = value;
|
||||
values[current&1023].color = color;
|
||||
current++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SCR_DrawDebugGraph
|
||||
==============
|
||||
*/
|
||||
void SCR_DrawDebugGraph (void)
|
||||
{
|
||||
#ifndef _XBOX
|
||||
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, cls.whiteShader );
|
||||
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, cls.whiteShader );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
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);
|
||||
#ifndef FINAL_BUILD
|
||||
cl_debugVoice = Cvar_Get ("debugVoice", "1", 0);
|
||||
#endif
|
||||
scr_initialized = qtrue;
|
||||
}
|
||||
|
||||
|
||||
//=======================================================
|
||||
|
||||
/*
|
||||
==================
|
||||
SCR_DrawScreenField
|
||||
|
||||
This will be called twice if rendering in stereo mode
|
||||
==================
|
||||
*/
|
||||
|
||||
void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
|
||||
re.BeginFrame( stereoFrame );
|
||||
|
||||
#ifdef _XBOX
|
||||
// if(ClientManager::splitScreenMode == qtrue)
|
||||
// cls.state = ClientManager::ActiveClient().state;
|
||||
#endif
|
||||
|
||||
// wide aspect ratio screens need to have the sides cleared
|
||||
// unless they are displaying game renderings
|
||||
#ifndef _XBOX
|
||||
// Xbox no likey
|
||||
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, cls.whiteShader );
|
||||
re.SetColor( NULL );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( !uivm ) {
|
||||
Com_DPrintf("draw screen without UI loaded\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// if the menu is going to cover the entire screen, we
|
||||
// don't need to render anything under it
|
||||
//actually, yes you do, unless you want clients to cycle out their reliable
|
||||
//commands from sitting in the menu. -rww
|
||||
if ( !VM_Call( uivm, UI_IS_FULLSCREEN ) || (!(cls.framecount&7) && cls.state == CA_ACTIVE)) {
|
||||
|
||||
switch( cls.state ) {
|
||||
default:
|
||||
#ifdef _XBOX
|
||||
if(ClientManager::splitScreenMode == qfalse)
|
||||
#endif
|
||||
Com_Error( ERR_FATAL, "SCR_DrawScreenField: bad cls.state" );
|
||||
break;
|
||||
case CA_CINEMATIC:
|
||||
SCR_DrawCinematic();
|
||||
break;
|
||||
case CA_DISCONNECTED:
|
||||
// force menu up
|
||||
S_StopAllSounds();
|
||||
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
|
||||
// refresh to update the time
|
||||
VM_Call( uivm, UI_REFRESH, cls.realtime );
|
||||
VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, qfalse );
|
||||
break;
|
||||
case CA_LOADING:
|
||||
case CA_PRIMED:
|
||||
// also draw the connection information, so it doesn't
|
||||
// flash away too briefly on local or lan games
|
||||
// refresh to update the time
|
||||
VM_Call( uivm, UI_REFRESH, cls.realtime );
|
||||
VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, qtrue );
|
||||
|
||||
// draw the game information screen and loading progress
|
||||
CL_CGameRendering( stereoFrame );
|
||||
break;
|
||||
case CA_ACTIVE:
|
||||
CL_CGameRendering( stereoFrame );
|
||||
// SCR_DrawDemoRecording();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// the menu draws next
|
||||
if ( cls.keyCatchers & KEYCATCH_UI && uivm ) {
|
||||
VM_Call( uivm, UI_REFRESH, cls.realtime );
|
||||
}
|
||||
|
||||
// console draws next
|
||||
Con_DrawConsole ();
|
||||
|
||||
#ifndef FINAL_BUILD
|
||||
// Debugging output for voice system
|
||||
if( cl_debugVoice->integer )
|
||||
g_Voice.DrawVoiceStats();
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
// debug graph can be drawn on top of anything
|
||||
if ( cl_debuggraph->integer || cl_timegraph->integer || cl_debugMove->integer ) {
|
||||
SCR_DrawDebugGraph ();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SCR_UpdateScreen
|
||||
|
||||
This is called every frame, and can also be called explicitly to flush
|
||||
text to the screen.
|
||||
==================
|
||||
*/
|
||||
#ifdef _XBOX
|
||||
int glcfgWidth = 640, glcfgHeight = 480, glcfgX = 0, glcfgY = 0;
|
||||
extern glconfig_t glConfig;
|
||||
#endif
|
||||
|
||||
void SCR_UpdateScreen( void ) {
|
||||
static int recursive;
|
||||
|
||||
if ( !scr_initialized ) {
|
||||
return; // not initialized yet
|
||||
}
|
||||
|
||||
if ( ++recursive > 2 ) {
|
||||
Com_Error( ERR_FATAL, "SCR_UpdateScreen: recursively called" );
|
||||
}
|
||||
recursive = 1;
|
||||
|
||||
#ifdef _XBOX
|
||||
qboolean rendered = qfalse;
|
||||
if (ClientManager::splitScreenMode == qtrue)
|
||||
{
|
||||
// cls.state = ClientManager::ActiveClient().state;
|
||||
|
||||
if (cls.state == CA_ACTIVE)
|
||||
{
|
||||
int lastClient = ClientManager::ActiveClientNum();
|
||||
ClientManager::SetMainClient(0);
|
||||
ClientManager::ActivateClient(0);
|
||||
|
||||
glcfgHeight = cgs.glconfig.vidHeight = 240;// glConfig.vidHeight = 240;
|
||||
ClientManager::SetMainClient(0);
|
||||
ClientManager::ActivateClient(0);
|
||||
SCR_DrawScreenField( STEREO_CENTER );
|
||||
|
||||
// Only draw the other screen if there are two clients
|
||||
if (ClientManager::NumClients() == 2)
|
||||
{
|
||||
glcfgY = 240;
|
||||
ClientManager::SetMainClient(1);
|
||||
ClientManager::ActivateClient(1);
|
||||
SCR_DrawScreenField( STEREO_CENTER );
|
||||
}
|
||||
|
||||
glcfgY = 0;
|
||||
glcfgHeight = cgs.glconfig.vidHeight = glConfig.vidHeight = 480;
|
||||
|
||||
ClientManager::SetMainClient(lastClient);
|
||||
ClientManager::ActivateClient(lastClient);
|
||||
|
||||
rendered = qtrue;
|
||||
}
|
||||
else
|
||||
rendered = qfalse;
|
||||
}
|
||||
|
||||
if(rendered == qfalse)
|
||||
{
|
||||
#endif
|
||||
|
||||
// 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 );
|
||||
}
|
||||
|
||||
#ifdef _XBOX
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( com_speeds->integer ) {
|
||||
re.EndFrame( &time_frontend, &time_backend );
|
||||
} else {
|
||||
re.EndFrame( NULL, NULL );
|
||||
}
|
||||
|
||||
recursive = 0;
|
||||
}
|
||||
|
||||
#define MAX_SCR_LINES 10
|
||||
|
||||
static float scr_centertime_off;
|
||||
int scr_center_y;
|
||||
//static string scr_font;
|
||||
static char scr_centerstring[1024];
|
||||
static int scr_center_lines;
|
||||
static int scr_center_widths[MAX_SCR_LINES];
|
||||
|
||||
cvar_t *scr_centertime;
|
||||
|
||||
void SCR_CenterPrint (char *str)//, PalIdx_t colour)
|
||||
{
|
||||
char *s, *last, *start, *write_pos, *save_pos;
|
||||
int num_chars;
|
||||
int num_lines;
|
||||
int width;
|
||||
bool done = false;
|
||||
bool spaced;
|
||||
|
||||
if (!str)
|
||||
{
|
||||
scr_centertime_off = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// scr_font = string("medium");
|
||||
|
||||
// RWL - commented out
|
||||
// width = viddef.width / 8; // rjr hardcoded yuckiness
|
||||
#ifdef _XBOX
|
||||
if(cg->widescreen)
|
||||
width = 720 / 8;
|
||||
else
|
||||
#endif
|
||||
width = 640 / 8; // rjr hardcoded yuckiness
|
||||
width -= 4;
|
||||
|
||||
// RWL - commented out
|
||||
/*
|
||||
if (cl.frame.playerstate.remote_type != REMOTE_TYPE_LETTERBOX)
|
||||
{
|
||||
width -= 30;
|
||||
}
|
||||
*/
|
||||
|
||||
scr_centertime_off = scr_centertime->value;
|
||||
|
||||
Com_Printf("\n");
|
||||
|
||||
num_lines = 0;
|
||||
write_pos = scr_centerstring;
|
||||
scr_center_lines = 0;
|
||||
spaced = false;
|
||||
for(s = start = str, last=NULL, num_chars = 0; !done ; s++)
|
||||
{
|
||||
num_chars++;
|
||||
if ((*s) == ' ')
|
||||
{
|
||||
spaced = true;
|
||||
last = s;
|
||||
scr_centertime_off += 0.2;//give them an extra 0.05 second for each character
|
||||
}
|
||||
|
||||
if ((*s) == '\n' || (*s) == 0)
|
||||
{
|
||||
last = s;
|
||||
num_chars = width;
|
||||
spaced = true;
|
||||
}
|
||||
|
||||
if (num_chars >= width)
|
||||
{
|
||||
scr_centertime_off += 0.8;//give them an extra half second for each newline
|
||||
if (!last)
|
||||
{
|
||||
last = s;
|
||||
}
|
||||
if (!spaced)
|
||||
{
|
||||
last++;
|
||||
}
|
||||
|
||||
save_pos = write_pos;
|
||||
strncpy(write_pos, start, last-start);
|
||||
write_pos += last-start;
|
||||
*write_pos = 0;
|
||||
write_pos++;
|
||||
|
||||
Com_Printf ("%s\n", save_pos);
|
||||
|
||||
// RWL - commented out
|
||||
// scr_center_widths[scr_center_lines] = re.StrlenFont(save_pos, scr_font);;
|
||||
#ifdef _XBOX
|
||||
if(cg->widescreen)
|
||||
scr_center_widths[scr_center_lines] = 720;
|
||||
else
|
||||
#endif
|
||||
scr_center_widths[scr_center_lines] = 640;
|
||||
|
||||
|
||||
scr_center_lines++;
|
||||
|
||||
if ((*s) == NULL || scr_center_lines >= MAX_SCR_LINES)
|
||||
{
|
||||
done = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
s = last;
|
||||
if (spaced)
|
||||
{
|
||||
last++;
|
||||
}
|
||||
start = last;
|
||||
last = NULL;
|
||||
num_chars = 0;
|
||||
spaced = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// echo it to the console
|
||||
Com_Printf("\n\n");
|
||||
Con_ClearNotify ();
|
||||
}
|
||||
882
codemp/client/cl_ui.cpp
Normal file
882
codemp/client/cl_ui.cpp
Normal file
@@ -0,0 +1,882 @@
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
#include "client.h"
|
||||
|
||||
#include "../game/botlib.h"
|
||||
#include "../qcommon/stringed_ingame.h"
|
||||
|
||||
/*
|
||||
Ghoul2 Insert Start
|
||||
*/
|
||||
|
||||
#if !defined(G2_H_INC)
|
||||
#include "../ghoul2/G2_local.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
Ghoul2 Insert End
|
||||
*/
|
||||
|
||||
#ifdef _XBOX
|
||||
#include "../cgame/cg_local.h"
|
||||
#include "../client/cl_data.h"
|
||||
#include "../renderer/modelmem.h"
|
||||
#endif
|
||||
|
||||
extern botlib_export_t *botlib_export;
|
||||
void SP_Register(const char *Package);
|
||||
|
||||
vm_t *uivm;
|
||||
|
||||
#ifdef USE_CD_KEY
|
||||
|
||||
extern char cl_cdkey[34];
|
||||
|
||||
#endif // USE_CD_KEY
|
||||
|
||||
/*
|
||||
====================
|
||||
GetClientState
|
||||
====================
|
||||
*/
|
||||
static void GetClientState( uiClientState_t *state ) {
|
||||
state->connectPacketCount = clc->connectPacketCount;
|
||||
#ifdef _XBOX
|
||||
// if(ClientManager::splitScreenMode == qtrue)
|
||||
// cls.state = ClientManager::ActiveClient().state;
|
||||
#endif
|
||||
state->connState = cls.state;
|
||||
Q_strncpyz( state->servername, cls.servername, sizeof( state->servername ) );
|
||||
Q_strncpyz( state->messageString, clc->serverMessage, sizeof( state->messageString ) );
|
||||
state->clientNum = cl->snap.ps.clientNum;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_GetGlConfig
|
||||
====================
|
||||
*/
|
||||
static void CL_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
|
||||
====================
|
||||
*/
|
||||
static 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;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
Ket_SetCatcher
|
||||
====================
|
||||
*/
|
||||
void Key_SetCatcher( int catcher ) {
|
||||
cls.keyCatchers = catcher;
|
||||
|
||||
#ifdef _XBOX
|
||||
if(catcher == KEYCATCH_UI)
|
||||
{
|
||||
// ModelMem.EnterUI();
|
||||
int i;
|
||||
|
||||
for(i=0; i<ClientManager::NumClients(); i++) {
|
||||
ClientManager::GetClient(i).swapMan1.SetUp();
|
||||
ClientManager::GetClient(i).swapMan2.SetUp();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ModelMem.ExitUI();
|
||||
//Horrible hack to make split screen work if force menus are skipped.
|
||||
extern int uiclientInputClosed;
|
||||
uiclientInputClosed = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_CD_KEY
|
||||
|
||||
/*
|
||||
====================
|
||||
CLUI_GetCDKey
|
||||
====================
|
||||
*/
|
||||
static void CLUI_GetCDKey( char *buf, int buflen ) {
|
||||
cvar_t *fs;
|
||||
fs = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO );
|
||||
if (UI_usesUniqueCDKey() && fs && fs->string[0] != 0) {
|
||||
Com_Memcpy( buf, &cl_cdkey[16], 16);
|
||||
buf[16] = 0;
|
||||
} else {
|
||||
Com_Memcpy( buf, cl_cdkey, 16);
|
||||
buf[16] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
CLUI_SetCDKey
|
||||
====================
|
||||
*/
|
||||
static void CLUI_SetCDKey( char *buf ) {
|
||||
cvar_t *fs;
|
||||
fs = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO );
|
||||
if (UI_usesUniqueCDKey() && fs && fs->string[0] != 0) {
|
||||
Com_Memcpy( &cl_cdkey[16], buf, 16 );
|
||||
cl_cdkey[32] = 0;
|
||||
// set the flag so the fle will be written at the next opportunity
|
||||
cvar_modifiedFlags |= CVAR_ARCHIVE;
|
||||
} else {
|
||||
Com_Memcpy( cl_cdkey, buf, 16 );
|
||||
// set the flag so the fle will be written at the next opportunity
|
||||
cvar_modifiedFlags |= CVAR_ARCHIVE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_CD_KEY
|
||||
|
||||
/*
|
||||
====================
|
||||
GetConfigString
|
||||
====================
|
||||
*/
|
||||
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) {
|
||||
if( size ) {
|
||||
buf[0] = 0;
|
||||
}
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
Q_strncpyz( buf, cl->gameState.stringData+offset, size);
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
FloatAsInt
|
||||
====================
|
||||
*/
|
||||
static int FloatAsInt( float f ) {
|
||||
int temp;
|
||||
|
||||
*(float *)&temp = f;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
void *VM_ArgPtr( int intValue );
|
||||
#define VMA(x) VM_ArgPtr(args[x])
|
||||
#define VMF(x) ((float *)args)[x]
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_UISystemCalls
|
||||
|
||||
The ui module is making a system call
|
||||
====================
|
||||
*/
|
||||
int CL_UISystemCalls( int *args ) {
|
||||
switch( args[0] ) {
|
||||
//rww - alright, DO NOT EVER add a GAME/CGAME/UI generic call without adding a trap to match, and
|
||||
//all of these traps must be shared and have cases in sv_game, cl_cgame, and cl_ui. They must also
|
||||
//all be in the same order, and start at 100.
|
||||
case TRAP_MEMSET:
|
||||
Com_Memset( VMA(1), args[2], args[3] );
|
||||
return 0;
|
||||
case TRAP_MEMCPY:
|
||||
Com_Memcpy( VMA(1), VMA(2), args[3] );
|
||||
return 0;
|
||||
case TRAP_STRNCPY:
|
||||
return (int)strncpy( (char *)VMA(1), (const char *)VMA(2), args[3] );
|
||||
case TRAP_SIN:
|
||||
return FloatAsInt( sin( VMF(1) ) );
|
||||
case TRAP_COS:
|
||||
return FloatAsInt( cos( VMF(1) ) );
|
||||
case TRAP_ATAN2:
|
||||
return FloatAsInt( atan2( VMF(1), VMF(2) ) );
|
||||
case TRAP_SQRT:
|
||||
return FloatAsInt( sqrt( VMF(1) ) );
|
||||
case TRAP_MATRIXMULTIPLY:
|
||||
MatrixMultiply( (vec3_t *)VMA(1), (vec3_t *)VMA(2), (vec3_t *)VMA(3) );
|
||||
return 0;
|
||||
case TRAP_ANGLEVECTORS:
|
||||
AngleVectors( (const float *)VMA(1), (float *)VMA(2), (float *)VMA(3), (float *)VMA(4) );
|
||||
return 0;
|
||||
case TRAP_PERPENDICULARVECTOR:
|
||||
PerpendicularVector( (float *)VMA(1), (const float *)VMA(2) );
|
||||
return 0;
|
||||
case TRAP_FLOOR:
|
||||
return FloatAsInt( floor( VMF(1) ) );
|
||||
case TRAP_CEIL:
|
||||
return FloatAsInt( ceil( VMF(1) ) );
|
||||
case TRAP_TESTPRINTINT:
|
||||
return 0;
|
||||
case TRAP_TESTPRINTFLOAT:
|
||||
return 0;
|
||||
case TRAP_ACOS:
|
||||
return FloatAsInt( Q_acos( VMF(1) ) );
|
||||
case TRAP_ASIN:
|
||||
return FloatAsInt( Q_asin( VMF(1) ) );
|
||||
|
||||
|
||||
case UI_ERROR:
|
||||
Com_Error( ERR_DROP, "%s", VMA(1) );
|
||||
return 0;
|
||||
|
||||
case UI_PRINT:
|
||||
Com_Printf( "%s", VMA(1) );
|
||||
return 0;
|
||||
|
||||
case UI_MILLISECONDS:
|
||||
return Sys_Milliseconds();
|
||||
|
||||
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_UPDATE:
|
||||
Cvar_Update( (vmCvar_t *)VMA(1) );
|
||||
return 0;
|
||||
|
||||
case UI_CVAR_SET:
|
||||
Cvar_Set( (const char *)VMA(1), (const char *)VMA(2) );
|
||||
return 0;
|
||||
|
||||
case UI_CVAR_VARIABLEVALUE:
|
||||
return FloatAsInt( Cvar_VariableValue( (const char *)VMA(1) ) );
|
||||
|
||||
case UI_CVAR_VARIABLESTRINGBUFFER:
|
||||
Cvar_VariableStringBuffer( (const char *)VMA(1), (char *)VMA(2), args[3] );
|
||||
return 0;
|
||||
|
||||
case UI_CVAR_SETVALUE:
|
||||
Cvar_SetValue( (const char *)VMA(1), VMF(2) );
|
||||
return 0;
|
||||
|
||||
case UI_CVAR_RESET:
|
||||
Cvar_Reset( (const char *)VMA(1) );
|
||||
return 0;
|
||||
|
||||
case UI_CVAR_CREATE:
|
||||
Cvar_Get( (const char *)VMA(1), (const char *)VMA(2), args[3] );
|
||||
return 0;
|
||||
|
||||
case UI_CVAR_INFOSTRINGBUFFER:
|
||||
Cvar_InfoStringBuffer( args[1], (char *)VMA(2), args[3] );
|
||||
return 0;
|
||||
|
||||
case UI_ARGC:
|
||||
return Cmd_Argc();
|
||||
|
||||
case UI_ARGV:
|
||||
Cmd_ArgvBuffer( args[1], (char *)VMA(2), args[3] );
|
||||
return 0;
|
||||
|
||||
case UI_CMD_EXECUTETEXT:
|
||||
Cbuf_ExecuteText( args[1], (const char *)VMA(2) );
|
||||
return 0;
|
||||
|
||||
case UI_FS_FOPENFILE:
|
||||
return FS_FOpenFileByMode( (const char *)VMA(1), (int *)VMA(2), (fsMode_t)args[3] );
|
||||
|
||||
case UI_FS_READ:
|
||||
FS_Read2( VMA(1), args[2], args[3] );
|
||||
return 0;
|
||||
|
||||
case UI_FS_WRITE:
|
||||
FS_Write( VMA(1), args[2], args[3] );
|
||||
return 0;
|
||||
|
||||
case UI_FS_FCLOSEFILE:
|
||||
FS_FCloseFile( args[1] );
|
||||
return 0;
|
||||
|
||||
case UI_FS_GETFILELIST:
|
||||
return FS_GetFileList( (const char *)VMA(1), (const char *)VMA(2), (char *)VMA(3), args[4] );
|
||||
|
||||
case UI_R_REGISTERMODEL:
|
||||
return re.RegisterModel( (const char *)VMA(1) );
|
||||
|
||||
case UI_R_REGISTERSKIN:
|
||||
return re.RegisterSkin( (const char *)VMA(1) );
|
||||
|
||||
case UI_R_REGISTERSHADERNOMIP:
|
||||
return re.RegisterShaderNoMip( (const char *)VMA(1) );
|
||||
|
||||
case UI_R_SHADERNAMEFROMINDEX:
|
||||
{
|
||||
char *gameMem = (char *)VMA(1);
|
||||
const char *retMem = re.ShaderNameFromIndex(args[2]);
|
||||
if (retMem)
|
||||
{
|
||||
strcpy(gameMem, retMem);
|
||||
}
|
||||
else
|
||||
{
|
||||
gameMem[0] = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
case UI_R_CLEARSCENE:
|
||||
re.ClearScene();
|
||||
return 0;
|
||||
|
||||
case UI_R_ADDREFENTITYTOSCENE:
|
||||
re.AddRefEntityToScene( (const refEntity_t *)VMA(1) );
|
||||
return 0;
|
||||
|
||||
case UI_R_ADDPOLYTOSCENE:
|
||||
re.AddPolyToScene( args[1], args[2], (const polyVert_t *)VMA(3), 1 );
|
||||
return 0;
|
||||
|
||||
case UI_R_ADDLIGHTTOSCENE:
|
||||
re.AddLightToScene( (const float *)VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) );
|
||||
return 0;
|
||||
|
||||
case UI_R_RENDERSCENE:
|
||||
re.RenderScene( (const refdef_t *)VMA(1) );
|
||||
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_R_MODELBOUNDS:
|
||||
re.ModelBounds( args[1], (float *)VMA(2), (float *)VMA(3) );
|
||||
return 0;
|
||||
|
||||
case UI_UPDATESCREEN:
|
||||
SCR_UpdateScreen();
|
||||
return 0;
|
||||
|
||||
case UI_CM_LERPTAG:
|
||||
re.LerpTag( (orientation_t *)VMA(1), args[2], args[3], args[4], VMF(5), (const char *)VMA(6) );
|
||||
return 0;
|
||||
|
||||
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_KEY_KEYNUMTOSTRINGBUF:
|
||||
Key_KeynumToStringBuf( args[1], (char *)VMA(2), args[3] );
|
||||
return 0;
|
||||
|
||||
case UI_KEY_GETBINDINGBUF:
|
||||
Key_GetBindingBuf( args[1], (char *)VMA(2), args[3] );
|
||||
return 0;
|
||||
|
||||
case UI_KEY_SETBINDING:
|
||||
Key_SetBinding( args[1], (const char *)VMA(2) );
|
||||
return 0;
|
||||
|
||||
case UI_KEY_ISDOWN:
|
||||
return Key_IsDown( args[1] );
|
||||
|
||||
case UI_KEY_GETOVERSTRIKEMODE:
|
||||
return Key_GetOverstrikeMode();
|
||||
|
||||
case UI_KEY_SETOVERSTRIKEMODE:
|
||||
Key_SetOverstrikeMode( (qboolean)args[1] );
|
||||
return 0;
|
||||
|
||||
case UI_KEY_CLEARSTATES:
|
||||
Key_ClearStates();
|
||||
return 0;
|
||||
|
||||
case UI_KEY_GETCATCHER:
|
||||
return Key_GetCatcher();
|
||||
|
||||
case UI_KEY_SETCATCHER:
|
||||
Key_SetCatcher( args[1] );
|
||||
return 0;
|
||||
|
||||
case UI_GETCLIPBOARDDATA:
|
||||
GetClipboardData( (char *)VMA(1), args[2] );
|
||||
return 0;
|
||||
|
||||
case UI_GETCLIENTSTATE:
|
||||
GetClientState( (uiClientState_t *)VMA(1) );
|
||||
return 0;
|
||||
|
||||
case UI_GETGLCONFIG:
|
||||
CL_GetGlconfig( (glconfig_t *)VMA(1) );
|
||||
return 0;
|
||||
|
||||
case UI_GETCONFIGSTRING:
|
||||
return GetConfigString( args[1], (char *)VMA(2), args[3] );
|
||||
|
||||
case UI_MEMORY_REMAINING:
|
||||
return Hunk_MemoryRemaining();
|
||||
|
||||
#ifdef USE_CD_KEY
|
||||
case UI_GET_CDKEY:
|
||||
CLUI_GetCDKey( (char *)VMA(1), args[2] );
|
||||
return 0;
|
||||
|
||||
case UI_SET_CDKEY:
|
||||
CLUI_SetCDKey( (char *)VMA(1) );
|
||||
return 0;
|
||||
#endif // USE_CD_KEY
|
||||
|
||||
case UI_R_REGISTERFONT:
|
||||
return re.RegisterFont( (const char *)VMA(1) );
|
||||
|
||||
case UI_R_FONT_STRLENPIXELS:
|
||||
return re.Font_StrLenPixels( (const char *)VMA(1), args[2], VMF(3) );
|
||||
|
||||
case UI_R_FONT_STRLENCHARS:
|
||||
return re.Font_StrLenChars( (const char *)VMA(1) );
|
||||
|
||||
case UI_R_FONT_STRHEIGHTPIXELS:
|
||||
return re.Font_HeightPixels( args[1], VMF(2) );
|
||||
|
||||
case UI_R_FONT_DRAWSTRING:
|
||||
re.Font_DrawString( args[1], args[2], (const char *)VMA(3), (const float *) VMA(4), args[5], args[6], VMF(7) );
|
||||
return 0;
|
||||
|
||||
case UI_LANGUAGE_ISASIAN:
|
||||
return re.Language_IsAsian();
|
||||
|
||||
case UI_LANGUAGE_USESSPACES:
|
||||
return re.Language_UsesSpaces();
|
||||
|
||||
case UI_ANYLANGUAGE_READCHARFROMSTRING:
|
||||
return re.AnyLanguage_ReadCharFromString( (const char *)VMA(1), (int *) VMA(2), (qboolean *) VMA(3) );
|
||||
|
||||
case UI_PC_ADD_GLOBAL_DEFINE:
|
||||
return botlib_export->PC_AddGlobalDefine( (char *)VMA(1) );
|
||||
case UI_PC_LOAD_SOURCE:
|
||||
return botlib_export->PC_LoadSourceHandle( (const char *)VMA(1) );
|
||||
case UI_PC_FREE_SOURCE:
|
||||
return botlib_export->PC_FreeSourceHandle( args[1] );
|
||||
case UI_PC_READ_TOKEN:
|
||||
return botlib_export->PC_ReadTokenHandle( args[1], (struct pc_token_s *)VMA(2) );
|
||||
case UI_PC_SOURCE_FILE_AND_LINE:
|
||||
return botlib_export->PC_SourceFileAndLine( args[1], (char *)VMA(2), (int *)VMA(3) );
|
||||
case UI_PC_LOAD_GLOBAL_DEFINES:
|
||||
return botlib_export->PC_LoadGlobalDefines ( (char *)VMA(1) );
|
||||
case UI_PC_REMOVE_ALL_GLOBAL_DEFINES:
|
||||
botlib_export->PC_RemoveAllGlobalDefines ( );
|
||||
return 0;
|
||||
|
||||
case UI_S_STOPBACKGROUNDTRACK:
|
||||
S_StopBackgroundTrack();
|
||||
return 0;
|
||||
case UI_S_STARTBACKGROUNDTRACK:
|
||||
S_StartBackgroundTrack( (const char *)VMA(1), (const char *)VMA(2), qfalse);
|
||||
return 0;
|
||||
|
||||
case UI_REAL_TIME:
|
||||
return Com_RealTime( (struct qtime_s *)VMA(1) );
|
||||
|
||||
case UI_R_REMAP_SHADER:
|
||||
re.RemapShader( (const char *)VMA(1), (const char *)VMA(2), (const char *)VMA(3) );
|
||||
return 0;
|
||||
|
||||
#ifdef USE_CD_KEY
|
||||
case UI_VERIFY_CDKEY:
|
||||
return CL_CDKeyValidate((const char *)VMA(1), (const char *)VMA(2));
|
||||
#endif // USE_CD_KEY
|
||||
|
||||
case UI_SP_GETNUMLANGUAGES:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
// return SE_GetNumLanguages();
|
||||
|
||||
case UI_SP_GETLANGUAGENAME:
|
||||
assert( 0 );
|
||||
return 0;
|
||||
|
||||
case UI_SP_GETSTRINGTEXTSTRING:
|
||||
const char* text;
|
||||
|
||||
assert(VMA(1));
|
||||
assert(VMA(2));
|
||||
text = SE_GetString((const char *) VMA(1));
|
||||
Q_strncpyz( (char *) VMA(2), text, args[3] );
|
||||
return qtrue;
|
||||
|
||||
/*
|
||||
Ghoul2 Insert Start
|
||||
*/
|
||||
/*
|
||||
Ghoul2 Insert Start
|
||||
*/
|
||||
|
||||
case UI_G2_LISTSURFACES:
|
||||
G2API_ListSurfaces( (CGhoul2Info *) args[1] );
|
||||
return 0;
|
||||
|
||||
case UI_G2_LISTBONES:
|
||||
G2API_ListBones( (CGhoul2Info *) args[1], args[2]);
|
||||
return 0;
|
||||
|
||||
case UI_G2_HAVEWEGHOULMODELS:
|
||||
return G2API_HaveWeGhoul2Models( *((CGhoul2Info_v *)args[1]) );
|
||||
|
||||
case UI_G2_SETMODELS:
|
||||
G2API_SetGhoul2ModelIndexes( *((CGhoul2Info_v *)args[1]),(qhandle_t *)VMA(2),(qhandle_t *)VMA(3));
|
||||
return 0;
|
||||
|
||||
case UI_G2_GETBOLT:
|
||||
return G2API_GetBoltMatrix(*((CGhoul2Info_v *)args[1]), args[2], args[3], (mdxaBone_t *)VMA(4), (const float *)VMA(5),(const float *)VMA(6), args[7], (qhandle_t *)VMA(8), (float *)VMA(9));
|
||||
|
||||
case UI_G2_GETBOLT_NOREC:
|
||||
gG2_GBMNoReconstruct = qtrue;
|
||||
return G2API_GetBoltMatrix(*((CGhoul2Info_v *)args[1]), args[2], args[3], (mdxaBone_t *)VMA(4), (const float *)VMA(5),(const float *)VMA(6), args[7], (qhandle_t *)VMA(8), (float *)VMA(9));
|
||||
|
||||
case UI_G2_GETBOLT_NOREC_NOROT:
|
||||
gG2_GBMNoReconstruct = qtrue;
|
||||
gG2_GBMUseSPMethod = qtrue;
|
||||
return G2API_GetBoltMatrix(*((CGhoul2Info_v *)args[1]), args[2], args[3], (mdxaBone_t *)VMA(4), (const float *)VMA(5),(const float *)VMA(6), args[7], (qhandle_t *)VMA(8), (float *)VMA(9));
|
||||
|
||||
case UI_G2_INITGHOUL2MODEL:
|
||||
#ifdef _FULL_G2_LEAK_CHECKING
|
||||
g_G2AllocServer = 0;
|
||||
#endif
|
||||
return G2API_InitGhoul2Model((CGhoul2Info_v **)VMA(1), (const char *)VMA(2), args[3], (qhandle_t) args[4],
|
||||
(qhandle_t) args[5], args[6], args[7]);
|
||||
|
||||
|
||||
case UI_G2_COLLISIONDETECT:
|
||||
return 0; //not supported for ui
|
||||
|
||||
case UI_G2_ANGLEOVERRIDE:
|
||||
return G2API_SetBoneAngles(*((CGhoul2Info_v *)args[1]), args[2], (const char *)VMA(3), (float *)VMA(4), args[5],
|
||||
(const Eorientations) args[6], (const Eorientations) args[7], (const Eorientations) args[8],
|
||||
(qhandle_t *)VMA(9), args[10], args[11] );
|
||||
|
||||
case UI_G2_CLEANMODELS:
|
||||
#ifdef _FULL_G2_LEAK_CHECKING
|
||||
g_G2AllocServer = 0;
|
||||
#endif
|
||||
G2API_CleanGhoul2Models((CGhoul2Info_v **)VMA(1));
|
||||
// G2API_CleanGhoul2Models((CGhoul2Info_v **)args[1]);
|
||||
return 0;
|
||||
|
||||
case UI_G2_PLAYANIM:
|
||||
return G2API_SetBoneAnim(*((CGhoul2Info_v *)args[1]), args[2], (const char *)VMA(3), args[4], args[5],
|
||||
args[6], VMF(7), args[8], VMF(9), args[10]);
|
||||
|
||||
case UI_G2_GETBONEANIM:
|
||||
{
|
||||
CGhoul2Info_v &g2 = *((CGhoul2Info_v *)args[1]);
|
||||
int modelIndex = args[10];
|
||||
|
||||
return G2API_GetBoneAnim(&g2[modelIndex], (const char*)VMA(2), args[3], (float *)VMA(4), (int *)VMA(5),
|
||||
(int *)VMA(6), (int *)VMA(7), (float *)VMA(8), (int *)VMA(9));
|
||||
}
|
||||
|
||||
case UI_G2_GETBONEFRAME:
|
||||
{ //rwwFIXMEFIXME: Just make a G2API_GetBoneFrame func too. This is dirty.
|
||||
CGhoul2Info_v &g2 = *((CGhoul2Info_v *)args[1]);
|
||||
int modelIndex = args[6];
|
||||
int iDontCare1 = 0, iDontCare2 = 0, iDontCare3 = 0;
|
||||
float fDontCare1 = 0;
|
||||
|
||||
return G2API_GetBoneAnim(&g2[modelIndex], (const char*)VMA(2), args[3], (float *)VMA(4), &iDontCare1,
|
||||
&iDontCare2, &iDontCare3, &fDontCare1, (int *)VMA(5));
|
||||
}
|
||||
|
||||
case UI_G2_GETGLANAME:
|
||||
// return (int)G2API_GetGLAName(*((CGhoul2Info_v *)VMA(1)), args[2]);
|
||||
{
|
||||
char *point = ((char *)VMA(3));
|
||||
char *local;
|
||||
local = G2API_GetGLAName(*((CGhoul2Info_v *)args[1]), args[2]);
|
||||
if (local)
|
||||
{
|
||||
strcpy(point, local);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
case UI_G2_COPYGHOUL2INSTANCE:
|
||||
return (int)G2API_CopyGhoul2Instance(*((CGhoul2Info_v *)args[1]), *((CGhoul2Info_v *)args[2]), args[3]);
|
||||
|
||||
case UI_G2_COPYSPECIFICGHOUL2MODEL:
|
||||
G2API_CopySpecificG2Model(*((CGhoul2Info_v *)args[1]), args[2], *((CGhoul2Info_v *)args[3]), args[4]);
|
||||
return 0;
|
||||
|
||||
case UI_G2_DUPLICATEGHOUL2INSTANCE:
|
||||
#ifdef _FULL_G2_LEAK_CHECKING
|
||||
g_G2AllocServer = 0;
|
||||
#endif
|
||||
G2API_DuplicateGhoul2Instance(*((CGhoul2Info_v *)args[1]), (CGhoul2Info_v **)VMA(2));
|
||||
return 0;
|
||||
|
||||
case UI_G2_HASGHOUL2MODELONINDEX:
|
||||
return (int)G2API_HasGhoul2ModelOnIndex((CGhoul2Info_v **)VMA(1), args[2]);
|
||||
//return (int)G2API_HasGhoul2ModelOnIndex((CGhoul2Info_v **)args[1], args[2]);
|
||||
|
||||
case UI_G2_REMOVEGHOUL2MODEL:
|
||||
#ifdef _FULL_G2_LEAK_CHECKING
|
||||
g_G2AllocServer = 0;
|
||||
#endif
|
||||
return (int)G2API_RemoveGhoul2Model((CGhoul2Info_v **)VMA(1), args[2]);
|
||||
//return (int)G2API_RemoveGhoul2Model((CGhoul2Info_v **)args[1], args[2]);
|
||||
|
||||
case UI_G2_ADDBOLT:
|
||||
return G2API_AddBolt(*((CGhoul2Info_v *)args[1]), args[2], (const char *)VMA(3));
|
||||
|
||||
// case UI_G2_REMOVEBOLT:
|
||||
// return G2API_RemoveBolt(*((CGhoul2Info_v *)VMA(1)), args[2]);
|
||||
|
||||
case UI_G2_SETBOLTON:
|
||||
G2API_SetBoltInfo(*((CGhoul2Info_v *)args[1]), args[2], args[3]);
|
||||
return 0;
|
||||
|
||||
#ifdef _SOF2
|
||||
case UI_G2_ADDSKINGORE:
|
||||
G2API_AddSkinGore(*((CGhoul2Info_v *)args[1]),*(SSkinGoreData *)VMA(2));
|
||||
return 0;
|
||||
#endif // _SOF2
|
||||
/*
|
||||
Ghoul2 Insert End
|
||||
*/
|
||||
case UI_G2_SETROOTSURFACE:
|
||||
return G2API_SetRootSurface(*((CGhoul2Info_v *)args[1]), args[2], (const char *)VMA(3));
|
||||
|
||||
case UI_G2_SETSURFACEONOFF:
|
||||
return G2API_SetSurfaceOnOff(*((CGhoul2Info_v *)args[1]), (const char *)VMA(2), /*(const int)VMA(3)*/args[3]);
|
||||
|
||||
case UI_G2_SETNEWORIGIN:
|
||||
return G2API_SetNewOrigin(*((CGhoul2Info_v *)args[1]), /*(const int)VMA(2)*/args[2]);
|
||||
|
||||
case UI_G2_GETTIME:
|
||||
return G2API_GetTime(0);
|
||||
|
||||
case UI_G2_SETTIME:
|
||||
G2API_SetTime(args[1], args[2]);
|
||||
return 0;
|
||||
|
||||
case UI_G2_SETRAGDOLL:
|
||||
return 0; //not supported for ui
|
||||
break;
|
||||
case UI_G2_ANIMATEG2MODELS:
|
||||
return 0; //not supported for ui
|
||||
break;
|
||||
|
||||
case UI_G2_SETBONEIKSTATE:
|
||||
return G2API_SetBoneIKState(*((CGhoul2Info_v *)args[1]), args[2], (const char *)VMA(3), args[4], (sharedSetBoneIKStateParams_t *)VMA(5));
|
||||
case UI_G2_IKMOVE:
|
||||
return G2API_IKMove(*((CGhoul2Info_v *)args[1]), args[2], (sharedIKMoveParams_t *)VMA(3));
|
||||
|
||||
case UI_G2_GETSURFACENAME:
|
||||
{ //Since returning a pointer in such a way to a VM seems to cause MASSIVE FAILURE<tm>, we will shove data into the pointer the vm passes instead
|
||||
char *point = ((char *)VMA(4));
|
||||
char *local;
|
||||
int modelindex = args[3];
|
||||
|
||||
CGhoul2Info_v &g2 = *((CGhoul2Info_v *)args[1]);
|
||||
|
||||
local = G2API_GetSurfaceName(&g2[modelindex], args[2]);
|
||||
if (local)
|
||||
{
|
||||
strcpy(point, local);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
case UI_G2_SETSKIN:
|
||||
{
|
||||
CGhoul2Info_v &g2 = *((CGhoul2Info_v *)args[1]);
|
||||
int modelIndex = args[2];
|
||||
|
||||
return G2API_SetSkin(&g2[modelIndex], args[3], args[4]);
|
||||
}
|
||||
|
||||
case UI_G2_ATTACHG2MODEL:
|
||||
{
|
||||
CGhoul2Info_v *g2From = ((CGhoul2Info_v *)args[1]);
|
||||
CGhoul2Info_v *g2To = ((CGhoul2Info_v *)args[3]);
|
||||
|
||||
return G2API_AttachG2Model(g2From[0], args[2], g2To[0], args[4], args[5]);
|
||||
}
|
||||
/*
|
||||
Ghoul2 Insert End
|
||||
*/
|
||||
default:
|
||||
Com_Error( ERR_DROP, "Bad UI system trap: %i", args[0] );
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_ShutdownUI
|
||||
====================
|
||||
*/
|
||||
void CL_ShutdownUI( void ) {
|
||||
cls.keyCatchers &= ~KEYCATCH_UI;
|
||||
cls.uiStarted = qfalse;
|
||||
if ( !uivm ) {
|
||||
return;
|
||||
}
|
||||
VM_Call( uivm, UI_SHUTDOWN );
|
||||
VM_Call( uivm, UI_MENU_RESET );
|
||||
VM_Free( uivm );
|
||||
uivm = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_InitUI
|
||||
====================
|
||||
*/
|
||||
|
||||
void CL_InitUI( void ) {
|
||||
int v;
|
||||
vmInterpret_t interpret;
|
||||
|
||||
// load the dll or bytecode
|
||||
if ( cl_connectedToPureServer != 0 ) {
|
||||
#if 0
|
||||
// if sv_pure is set we only allow qvms to be loaded
|
||||
interpret = VMI_COMPILED;
|
||||
#else //load the module type based on what the server is doing -rww
|
||||
interpret = (vmInterpret_t)cl_connectedUI;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
interpret = (vmInterpret_t)(int)Cvar_VariableValue( "vm_ui" );
|
||||
}
|
||||
uivm = VM_Create( "ui", CL_UISystemCalls, interpret );
|
||||
if ( !uivm ) {
|
||||
Com_Error( ERR_FATAL, "VM_Create on UI failed" );
|
||||
}
|
||||
|
||||
// sanity check
|
||||
v = VM_Call( uivm, UI_GETAPIVERSION );
|
||||
if (v != UI_API_VERSION) {
|
||||
Com_Error( ERR_DROP, "User Interface is version %d, expected %d", v, UI_API_VERSION );
|
||||
cls.uiStarted = qfalse;
|
||||
}
|
||||
else {
|
||||
// init for this gamestate
|
||||
//rww - changed to <= CA_ACTIVE, because that is the state when we did a vid_restart
|
||||
//ingame (was just < CA_ACTIVE before, resulting in ingame menus getting wiped and
|
||||
//not reloaded on vid restart from ingame menu)
|
||||
#ifdef _XBOX
|
||||
// if(ClientManager::splitScreenMode == qtrue)
|
||||
// cls.state = ClientManager::ActiveClient().state;
|
||||
#endif
|
||||
|
||||
#ifdef _XBOX
|
||||
// This is kinda a hack to get the UI models that are ALWAYS loaded
|
||||
// forced into the UI model memory slot
|
||||
// ModelMem.EnterUI();
|
||||
#endif
|
||||
VM_Call( uivm, UI_INIT, (cls.state >= CA_AUTHORIZING && cls.state <= CA_ACTIVE) );
|
||||
|
||||
#ifdef _XBOX
|
||||
// ModelMem.ExitUI();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
qboolean UI_usesUniqueCDKey() {
|
||||
if (uivm) {
|
||||
return (qboolean)(VM_Call( uivm, UI_HASUNIQUECDKEY) == qtrue);
|
||||
} else {
|
||||
return qfalse;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
UI_GameCommand
|
||||
|
||||
See if the current console command is claimed by the ui
|
||||
====================
|
||||
*/
|
||||
qboolean UI_GameCommand( void ) {
|
||||
if ( !uivm ) {
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
return (qboolean)VM_Call( uivm, UI_CONSOLE_COMMAND, cls.realtime );
|
||||
}
|
||||
575
codemp/client/client.h
Normal file
575
codemp/client/client.h
Normal file
@@ -0,0 +1,575 @@
|
||||
// client.h -- primary header for client
|
||||
#pragma once
|
||||
#if !defined(CLIENT_H_INC)
|
||||
#define CLIENT_H_INC
|
||||
|
||||
#include "../game/q_shared.h"
|
||||
#include "../qcommon/qcommon.h"
|
||||
#include "../renderer/tr_public.h"
|
||||
#include "../ui/ui_public.h"
|
||||
#include "keys.h"
|
||||
#include "snd_public.h"
|
||||
#include "../cgame/cg_public.h"
|
||||
#include "../game/bg_public.h"
|
||||
|
||||
#ifdef _XBOX
|
||||
#include <xtl.h>
|
||||
#endif
|
||||
|
||||
#define RETRANSMIT_TIMEOUT 3000 // time between connection packet retransmits
|
||||
|
||||
// Wind
|
||||
extern vec3_t cl_windVec;
|
||||
|
||||
// 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
|
||||
playerState_t vps; //vehicle I'm riding's playerstate (if applicable) -rww
|
||||
|
||||
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
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int p_cmdNumber; // cl.cmdNumber when packet was sent
|
||||
int p_serverTime; // usercmd->serverTime when packet was sent
|
||||
int p_realtime; // cls.realtime when packet was sent
|
||||
} outPacket_t;
|
||||
|
||||
// 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
|
||||
#ifdef _XBOX
|
||||
#define MAX_PARSE_ENTITIES 1024
|
||||
#else
|
||||
#define MAX_PARSE_ENTITIES 2048
|
||||
#endif
|
||||
|
||||
extern int g_console_field_width;
|
||||
|
||||
typedef struct {
|
||||
int timeoutcount; // it requres several frames in a timeout condition
|
||||
// to disconnect, preventing debugging breaks from
|
||||
// causing immediate disconnects on continue
|
||||
clSnapshot_t snap; // latest received from server
|
||||
|
||||
int serverTime; // may be paused during play
|
||||
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 of any valid packet
|
||||
|
||||
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
|
||||
|
||||
// cgame communicates a few values to the client system
|
||||
int cgameUserCmdValue; // current weapon to add to usercmd_t
|
||||
vec3_t cgameViewAngleForce;
|
||||
int cgameViewAngleForceTime;
|
||||
float cgameSensitivity;
|
||||
|
||||
int cgameForceSelection;
|
||||
int cgameInvenSelection;
|
||||
|
||||
qboolean gcmdSendValue;
|
||||
qboolean gcmdSentValue;
|
||||
byte gcmdValue;
|
||||
|
||||
// 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
|
||||
|
||||
outPacket_t outPackets[PACKET_BACKUP]; // information about each packet we have sent out
|
||||
|
||||
// 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;
|
||||
|
||||
int serverId; // included in each client message so the server
|
||||
// can tell if it is for a prior map_restart
|
||||
// big stuff at end of structure so most offsets are 15 bits or less
|
||||
clSnapshot_t snapshots[PACKET_BACKUP];
|
||||
|
||||
entityState_t entityBaselines[MAX_GENTITIES]; // for delta compression when not in previous frame
|
||||
|
||||
entityState_t parseEntities[MAX_PARSE_ENTITIES];
|
||||
|
||||
char *mSharedMemory;
|
||||
} clientActive_t;
|
||||
|
||||
//extern clientActive_t g_cl;
|
||||
extern clientActive_t *cl;
|
||||
|
||||
#define MAX_HEIGHTMAP_SIZE 16000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int mType;
|
||||
int mSide;
|
||||
vec3_t mOrigin;
|
||||
|
||||
} rmAutomapSymbol_t;
|
||||
|
||||
#define MAX_AUTOMAP_SYMBOLS 512
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
the clientConnection_t structure is wiped when disconnecting from a server,
|
||||
either to go to a full screen console, play a demo, or connect to a different server
|
||||
|
||||
A connection can be to either a server through the network layer or a
|
||||
demo through a file.
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
||||
int clientNum;
|
||||
int lastPacketSentTime; // for retransmits during connection
|
||||
int lastPacketTime; // for timeouts
|
||||
|
||||
netadr_t serverAddress;
|
||||
int connectTime; // for connection retransmits
|
||||
int connectPacketCount; // for display on connection dialog
|
||||
char serverMessage[MAX_STRING_TOKENS]; // for display on connection dialog
|
||||
|
||||
int challenge; // from the server to use for connecting
|
||||
int checksumFeed; // from the server for checksum calculations
|
||||
|
||||
// these are our reliable messages that go to the server
|
||||
int reliableSequence;
|
||||
int reliableAcknowledge; // the last one the server has executed
|
||||
char reliableCommands[MAX_RELIABLE_COMMANDS][MAX_STRING_CHARS];
|
||||
|
||||
// server message (unreliable) and command (reliable) sequence
|
||||
// numbers are NOT cleared at level changes, but continue to
|
||||
// increase as long as the connection is valid
|
||||
|
||||
// message sequence is used by both the network layer and the
|
||||
// delta compression layer
|
||||
int serverMessageSequence;
|
||||
|
||||
// reliable messages received from server
|
||||
int serverCommandSequence;
|
||||
int lastExecutedServerCommand; // last server command grabbed or executed with CL_GetServerCommand
|
||||
char serverCommands[MAX_RELIABLE_COMMANDS][MAX_STRING_CHARS];
|
||||
|
||||
#ifndef _XBOX // No downloading or demos on Xbox
|
||||
// file transfer from server
|
||||
fileHandle_t download;
|
||||
char downloadTempName[MAX_OSPATH];
|
||||
char downloadName[MAX_OSPATH];
|
||||
int downloadNumber;
|
||||
int downloadBlock; // block we are waiting for
|
||||
int downloadCount; // how many bytes we got
|
||||
int downloadSize; // how many bytes we got
|
||||
char downloadList[MAX_INFO_STRING]; // list of paks we need to download
|
||||
qboolean downloadRestart; // if true, we need to do another FS_Restart because we downloaded a pak
|
||||
|
||||
// demo information
|
||||
char demoName[MAX_QPATH];
|
||||
qboolean spDemoRecording;
|
||||
qboolean demorecording;
|
||||
qboolean demoplaying;
|
||||
qboolean demowaiting; // don't record until a non-delta message is received
|
||||
qboolean firstDemoFrameSkipped;
|
||||
fileHandle_t demofile;
|
||||
|
||||
int timeDemoFrames; // counter of rendered frames
|
||||
int timeDemoStart; // cls.realtime before first frame
|
||||
int timeDemoBaseTime; // each frame will be at this time + frameNum * 50
|
||||
#endif
|
||||
|
||||
// big stuff at end of structure so most offsets are 15 bits or less
|
||||
netchan_t netchan;
|
||||
|
||||
//rwwRMG - added:
|
||||
/*
|
||||
int rmgSeed;
|
||||
int rmgHeightMapSize;
|
||||
unsigned char rmgHeightMap[MAX_HEIGHTMAP_SIZE];
|
||||
unsigned char rmgFlattenMap[MAX_HEIGHTMAP_SIZE];
|
||||
rmAutomapSymbol_t rmgAutomapSymbols[MAX_AUTOMAP_SYMBOLS];
|
||||
int rmgAutomapSymbolCount;
|
||||
*/
|
||||
} clientConnection_t;
|
||||
|
||||
extern clientConnection_t g_clc;
|
||||
extern clientConnection_t *clc;
|
||||
|
||||
/*
|
||||
==================================================================
|
||||
|
||||
the clientStatic_t structure is never wiped, and is used even when
|
||||
no client connection is active at all
|
||||
|
||||
==================================================================
|
||||
*/
|
||||
/*
|
||||
typedef struct {
|
||||
netadr_t adr;
|
||||
int start;
|
||||
int time;
|
||||
char info[MAX_INFO_STRING];
|
||||
XNADDR xnaddr;
|
||||
} ping_t;
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
// char hostName[MAX_NAME_LENGTH];
|
||||
char mapName[MAX_NAME_LENGTH];
|
||||
int gameType;
|
||||
int clients;
|
||||
int maxClients;
|
||||
|
||||
qboolean saberOnly;
|
||||
qboolean forceDisable;
|
||||
|
||||
XNKID SessionID;
|
||||
XNKEY KeyExchangeKey;
|
||||
XNADDR HostAddress;
|
||||
|
||||
int lastUpdate;
|
||||
} serverInfo_t;
|
||||
|
||||
typedef struct {
|
||||
byte ip[4];
|
||||
unsigned short port;
|
||||
} serverAddress_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;
|
||||
|
||||
int framecount;
|
||||
int frametime; // msec since last frame
|
||||
|
||||
int realtime; // ignores pause
|
||||
int realFrametime; // ignoring pause, so console always works
|
||||
|
||||
int numlocalservers;
|
||||
serverInfo_t localServers[MAX_OTHER_SERVERS];
|
||||
|
||||
int pingUpdateSource; // source currently pinging or updating
|
||||
|
||||
// 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; // for wide aspect screens
|
||||
|
||||
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 vm_t *cgvm; // interface to cgame dll or vm
|
||||
extern vm_t *uivm; // interface to ui dll or vm
|
||||
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_showSend;
|
||||
extern cvar_t *cl_timeNudge;
|
||||
extern cvar_t *cl_showTimeDelta;
|
||||
extern cvar_t *cl_freezeDemo;
|
||||
|
||||
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;
|
||||
extern cvar_t *cl_freelook;
|
||||
|
||||
extern cvar_t *cl_mouseAccel;
|
||||
extern cvar_t *cl_showMouseRate;
|
||||
|
||||
extern cvar_t *m_pitchVeh;
|
||||
extern cvar_t *m_yaw;
|
||||
extern cvar_t *m_forward;
|
||||
extern cvar_t *m_side;
|
||||
extern cvar_t *m_filter;
|
||||
|
||||
extern cvar_t *cl_timedemo;
|
||||
|
||||
extern cvar_t *cl_activeAction;
|
||||
|
||||
#ifndef _XBOX
|
||||
extern cvar_t *cl_allowDownload;
|
||||
extern cvar_t *cl_allowAltEnter;
|
||||
#endif
|
||||
extern cvar_t *cl_conXOffset;
|
||||
extern cvar_t *cl_inGameVideo;
|
||||
|
||||
//=================================================
|
||||
|
||||
//
|
||||
// cl_main
|
||||
//
|
||||
|
||||
void CL_Init (void);
|
||||
void CL_FlushMemory(void);
|
||||
void CL_ShutdownAll(void);
|
||||
void CL_AddReliableCommand( const char *cmd );
|
||||
|
||||
void CL_StartHunkUsers( void );
|
||||
|
||||
void CL_Disconnect_f (void);
|
||||
void CL_GetChallengePacket (void);
|
||||
void CL_Vid_Restart_f( void );
|
||||
void CL_Snd_Restart_f (void);
|
||||
void CL_StartDemoLoop( void );
|
||||
void CL_NextDemo( void );
|
||||
void CL_ReadDemoMessage( void );
|
||||
|
||||
void CL_InitDownloads(void);
|
||||
void CL_NextDownload(void);
|
||||
|
||||
//void CL_GetPing( int n, char *buf, int buflen, int *pingtime );
|
||||
void CL_GetPingInfo( int n, char *buf, int buflen );
|
||||
void CL_ClearPing( int n );
|
||||
int CL_GetPingQueueCount( void );
|
||||
|
||||
void CL_ShutdownRef( void );
|
||||
void CL_InitRef( void );
|
||||
|
||||
#ifdef USE_CD_KEY
|
||||
|
||||
qboolean CL_CDKeyValidate( const char *key, const char *checksum );
|
||||
|
||||
#endif // USE_CD_KEY
|
||||
|
||||
//int CL_ServerStatus( char *serverAddress, char *serverStatusString, int maxLen );
|
||||
|
||||
|
||||
//
|
||||
// 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_WritePacket( void );
|
||||
void IN_CenterView (void);
|
||||
|
||||
void CL_VerifyCode( 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
|
||||
//
|
||||
extern int cl_connectedToPureServer;
|
||||
extern int cl_connectedGAME;
|
||||
extern int cl_connectedCGAME;
|
||||
extern int cl_connectedUI;
|
||||
|
||||
void CL_SystemInfoChanged( void );
|
||||
void CL_ParseServerMessage( msg_t *msg );
|
||||
//void CL_SP_Print(const word ID, byte *Data);
|
||||
|
||||
//====================================================================
|
||||
|
||||
//void CL_ServerInfoPacket( netadr_t from, msg_t *msg );
|
||||
//void CL_LocalServers_f( void );
|
||||
//void CL_Ping_f( void );
|
||||
qboolean CL_UpdateVisiblePings_f( int source );
|
||||
|
||||
|
||||
//
|
||||
// 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);
|
||||
|
||||
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 );
|
||||
|
||||
//
|
||||
// cl_cin.c
|
||||
//
|
||||
|
||||
void CL_PlayCinematic_f( void );
|
||||
void SCR_DrawCinematic (void);
|
||||
void SCR_RunCinematic (void);
|
||||
void SCR_StopCinematic (void);
|
||||
int CIN_PlayCinematic( const char *arg0, int xpos, int ypos, int width, int height, int bits);
|
||||
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);
|
||||
|
||||
void CL_UpdateHotSwap(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 );
|
||||
void CL_ShaderStateChanged(void);
|
||||
|
||||
//
|
||||
// cl_ui.c
|
||||
//
|
||||
void CL_InitUI( void );
|
||||
void CL_ShutdownUI( void );
|
||||
int Key_GetCatcher( void );
|
||||
void Key_SetCatcher( int catcher );
|
||||
void LAN_LoadCachedServers();
|
||||
void LAN_SaveServersToCache();
|
||||
|
||||
|
||||
//
|
||||
// cl_net_chan.c
|
||||
//
|
||||
void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg); //int length, const byte *data );
|
||||
void CL_Netchan_TransmitNextFragment( netchan_t *chan );
|
||||
qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg );
|
||||
#endif
|
||||
1562
codemp/client/eax/eax.h
Normal file
1562
codemp/client/eax/eax.h
Normal file
File diff suppressed because it is too large
Load Diff
171
codemp/client/eax/eaxman.h
Normal file
171
codemp/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
|
||||
129
codemp/client/fffx.h
Normal file
129
codemp/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 //////////////////////
|
||||
|
||||
105
codemp/client/fxexport.cpp
Normal file
105
codemp/client/fxexport.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
#include "client.h"
|
||||
#include "FXScheduler.h"
|
||||
|
||||
//#define __FXCHECKER
|
||||
|
||||
#ifdef __FXCHECKER
|
||||
#include <float.h>
|
||||
#endif // __FXCHECKER
|
||||
|
||||
int FX_RegisterEffect(const char *file)
|
||||
{
|
||||
return theFxScheduler.RegisterEffect(file, true);
|
||||
}
|
||||
|
||||
void FX_PlayEffect( const char *file, vec3_t org, vec3_t fwd, int vol, int rad )
|
||||
{
|
||||
#ifdef __FXCHECKER
|
||||
if (_isnan(org[0]) || _isnan(org[1]) || _isnan(org[2]))
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
if (_isnan(fwd[0]) || _isnan(fwd[1]) || _isnan(fwd[2]))
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
if (fabs(fwd[0]) < 0.1 && fabs(fwd[1]) < 0.1 && fabs(fwd[2]) < 0.1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
#endif // __FXCHECKER
|
||||
|
||||
theFxScheduler.PlayEffect(file, org, fwd, vol, rad);
|
||||
}
|
||||
|
||||
void FX_PlayEffectID( int id, vec3_t org, vec3_t fwd, int vol, int rad, qboolean isPortal )
|
||||
{
|
||||
#ifdef __FXCHECKER
|
||||
if (_isnan(org[0]) || _isnan(org[1]) || _isnan(org[2]))
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
if (_isnan(fwd[0]) || _isnan(fwd[1]) || _isnan(fwd[2]))
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
if (fabs(fwd[0]) < 0.1 && fabs(fwd[1]) < 0.1 && fabs(fwd[2]) < 0.1)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
#endif // __FXCHECKER
|
||||
|
||||
theFxScheduler.PlayEffect(id, org, fwd, vol, rad, !!isPortal );
|
||||
}
|
||||
|
||||
void FX_PlayBoltedEffectID( int id, vec3_t org,
|
||||
const int boltInfo, int iGhoul2, int iLooptime, qboolean isRelative )
|
||||
{
|
||||
theFxScheduler.PlayEffect(id, org, 0, boltInfo, iGhoul2, -1, -1, -1, qfalse, iLooptime, !!isRelative );
|
||||
}
|
||||
|
||||
void FX_PlayEntityEffectID( int id, vec3_t org,
|
||||
vec3_t axis[3], const int boltInfo, const int entNum, int vol, int rad )
|
||||
{
|
||||
#ifdef __FXCHECKER
|
||||
if (_isnan(org[0]) || _isnan(org[1]) || _isnan(org[2]))
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
#endif // __FXCHECKER
|
||||
|
||||
theFxScheduler.PlayEffect(id, org, axis, boltInfo, NULL, -1, vol, rad );
|
||||
}
|
||||
|
||||
void FX_AddScheduledEffects( qboolean portal )
|
||||
{
|
||||
theFxScheduler.AddScheduledEffects(!!portal);
|
||||
}
|
||||
|
||||
void FX_Draw2DEffects( float screenXScale, float screenYScale )
|
||||
{
|
||||
theFxScheduler.Draw2DEffects( screenXScale, screenYScale );
|
||||
}
|
||||
|
||||
int FX_InitSystem( refdef_t* refdef )
|
||||
{
|
||||
return FX_Init( refdef );
|
||||
}
|
||||
|
||||
void FX_SetRefDefFromCGame( refdef_t* refdef )
|
||||
{
|
||||
FX_SetRefDef( refdef );
|
||||
}
|
||||
|
||||
qboolean FX_FreeSystem( void )
|
||||
{
|
||||
return (qboolean)FX_Free( true );
|
||||
}
|
||||
|
||||
void FX_AdjustTime( int time )
|
||||
{
|
||||
theFxHelper.AdjustTime(time);
|
||||
}
|
||||
23
codemp/client/fxexport.h
Normal file
23
codemp/client/fxexport.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef FX_EXPORT_H_INC
|
||||
#define FX_EXPORT_H_INC
|
||||
|
||||
int FX_RegisterEffect(const char *file);
|
||||
|
||||
void FX_PlayEffect( const char *file, vec3_t org, vec3_t fwd, int vol, int rad ); // builds arbitrary perp. right vector, does a cross product to define up
|
||||
|
||||
void FX_PlayEffectID( int id, vec3_t org, vec3_t fwd, int vol, int rad, qboolean isPortal = qfalse ); // builds arbitrary perp. right vector, does a cross product to define up
|
||||
void FX_PlayEntityEffectID( int id, vec3_t org,
|
||||
vec3_t axis[3], const int boltInfo, const int entNum, int vol, int rad );
|
||||
void FX_PlayBoltedEffectID( int id, vec3_t org,
|
||||
const int boltInfo, int iGhoul2, int iLooptime, qboolean isRelative );
|
||||
|
||||
void FX_AddScheduledEffects( qboolean portal );
|
||||
void FX_Draw2DEffects ( float screenXScale, float screenYScale );
|
||||
|
||||
int FX_InitSystem( refdef_t* refdef ); // called in CG_Init to purge the fx system.
|
||||
void FX_SetRefDefFromCGame( refdef_t* refdef );
|
||||
qboolean FX_FreeSystem( void ); // ditches all active effects;
|
||||
void FX_AdjustTime( int time );
|
||||
|
||||
|
||||
#endif // FX_EXPORT_H_INC
|
||||
2497
codemp/client/fxprimitives.cpp
Normal file
2497
codemp/client/fxprimitives.cpp
Normal file
File diff suppressed because it is too large
Load Diff
611
codemp/client/fxprimitives.h
Normal file
611
codemp/client/fxprimitives.h
Normal file
@@ -0,0 +1,611 @@
|
||||
|
||||
#if !defined(FX_SYSTEM_H_INC)
|
||||
#include "FxSystem.h"
|
||||
#endif
|
||||
|
||||
#ifndef FX_PRIMITIVES_H_INC
|
||||
#define FX_PRIMITIVES_H_INC
|
||||
|
||||
|
||||
#define MAX_EFFECTS 1800
|
||||
|
||||
// Generic group flags, used by parser, then get converted to the appropriate specific flags
|
||||
#define FX_PARM_MASK 0xC // use this to mask off any transition types that use a parm
|
||||
#define FX_GENERIC_MASK 0xF
|
||||
#define FX_LINEAR 0x1
|
||||
#define FX_RAND 0x2
|
||||
#define FX_NONLINEAR 0x4
|
||||
#define FX_WAVE 0x8
|
||||
#define FX_CLAMP 0xC
|
||||
|
||||
// Group flags
|
||||
#define FX_ALPHA_SHIFT 0
|
||||
#define FX_ALPHA_PARM_MASK 0x0000000C
|
||||
#define FX_ALPHA_LINEAR 0x00000001
|
||||
#define FX_ALPHA_RAND 0x00000002
|
||||
#define FX_ALPHA_NONLINEAR 0x00000004
|
||||
#define FX_ALPHA_WAVE 0x00000008
|
||||
#define FX_ALPHA_CLAMP 0x0000000C
|
||||
|
||||
#define FX_RGB_SHIFT 4
|
||||
#define FX_RGB_PARM_MASK 0x000000C0
|
||||
#define FX_RGB_LINEAR 0x00000010
|
||||
#define FX_RGB_RAND 0x00000020
|
||||
#define FX_RGB_NONLINEAR 0x00000040
|
||||
#define FX_RGB_WAVE 0x00000080
|
||||
#define FX_RGB_CLAMP 0x000000C0
|
||||
|
||||
#define FX_SIZE_SHIFT 8
|
||||
#define FX_SIZE_PARM_MASK 0x00000C00
|
||||
#define FX_SIZE_LINEAR 0x00000100
|
||||
#define FX_SIZE_RAND 0x00000200
|
||||
#define FX_SIZE_NONLINEAR 0x00000400
|
||||
#define FX_SIZE_WAVE 0x00000800
|
||||
#define FX_SIZE_CLAMP 0x00000C00
|
||||
|
||||
#define FX_LENGTH_SHIFT 12
|
||||
#define FX_LENGTH_PARM_MASK 0x0000C000
|
||||
#define FX_LENGTH_LINEAR 0x00001000
|
||||
#define FX_LENGTH_RAND 0x00002000
|
||||
#define FX_LENGTH_NONLINEAR 0x00004000
|
||||
#define FX_LENGTH_WAVE 0x00008000
|
||||
#define FX_LENGTH_CLAMP 0x0000C000
|
||||
|
||||
#define FX_SIZE2_SHIFT 16
|
||||
#define FX_SIZE2_PARM_MASK 0x000C0000
|
||||
#define FX_SIZE2_LINEAR 0x00010000
|
||||
#define FX_SIZE2_RAND 0x00020000
|
||||
#define FX_SIZE2_NONLINEAR 0x00040000
|
||||
#define FX_SIZE2_WAVE 0x00080000
|
||||
#define FX_SIZE2_CLAMP 0x000C0000
|
||||
|
||||
// Shared flag--these flags, at first glance would appear to be shared, but are safe. I'd rather not do this, but as you can see, features flags are currently all accounted for
|
||||
#define FX_PAPER_PHYSICS 0x00010000 // emitters ONLY. shared with FX_SIZE_2_LINEAR
|
||||
#define FX_LOCALIZED_FLASH 0x00010000 // full screen flashes ONLY. shared with FX_SIZE_2_LINEAR
|
||||
#define FX_PLAYER_VIEW 0x00010000 // player view effects ONLY. shared with FX_SIZE_2_LINEAR
|
||||
|
||||
// Feature flags
|
||||
#define FX_DEPTH_HACK 0x00100000
|
||||
#define FX_RELATIVE 0x00200000
|
||||
#define FX_SET_SHADER_TIME 0x00400000
|
||||
#define FX_EXPENSIVE_PHYSICS 0x00800000
|
||||
|
||||
//rww - g2-related flags (these can slow things down significantly, use sparingly)
|
||||
//These should be used only with particles/decals as they steal flags used by cylinders.
|
||||
#define FX_GHOUL2_TRACE 0x00020000 //use in conjunction with particles - actually do full ghoul2 traces for physics collision against entities with a ghoul2 instance
|
||||
//shared FX_SIZE2_RAND (used only with cylinders)
|
||||
#define FX_GHOUL2_DECALS 0x00040000 //use in conjunction with decals - can project decal as a ghoul2 gore skin object onto ghoul2 models
|
||||
//shared FX_SIZE2_NONLINEAR (used only with cylinders)
|
||||
|
||||
#define FX_ATTACHED_MODEL 0x01000000
|
||||
|
||||
#define FX_APPLY_PHYSICS 0x02000000
|
||||
#define FX_USE_BBOX 0x04000000 // can make physics more accurate at the expense of speed
|
||||
|
||||
#define FX_USE_ALPHA 0x08000000 // the FX system actually uses RGB to do fades, but this will override that
|
||||
// and cause it to fill in the alpha.
|
||||
|
||||
#define FX_EMIT_FX 0x10000000 // emitters technically don't have to emit stuff, but when they do
|
||||
// this flag needs to be set
|
||||
#define FX_DEATH_RUNS_FX 0x20000000 // Normal death triggers effect, but not kill_on_impact
|
||||
#define FX_KILL_ON_IMPACT 0x40000000 // works just like it says, but only when physics are on.
|
||||
#define FX_IMPACT_RUNS_FX 0x80000000 // an effect can call another effect when it hits something.
|
||||
|
||||
// Lightning flags, duplicates of existing flags, but lightning doesn't use those flags in that context...and nothing will ever use these in this context..so we are safe.
|
||||
#define FX_TAPER 0x01000000 // tapers as it moves towards its endpoint
|
||||
#define FX_BRANCH 0x02000000 // enables lightning branching
|
||||
#define FX_GROW 0x04000000 // lightning grows from start point to end point over the course of its life
|
||||
|
||||
|
||||
// stuff that can occur when an effect is flagged with "materialImpact" and it hits something
|
||||
enum EMatImpactEffect
|
||||
{
|
||||
MATIMPACTFX_NONE = 0,
|
||||
MATIMPACTFX_SHELLSOUND
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
class CEffect
|
||||
{
|
||||
protected:
|
||||
|
||||
CEffect *mNext;
|
||||
vec3_t mOrigin1;
|
||||
|
||||
int mTimeStart;
|
||||
int mTimeEnd;
|
||||
|
||||
unsigned int mFlags;
|
||||
|
||||
EMatImpactEffect mMatImpactFX;
|
||||
int mMatImpactParm;
|
||||
|
||||
// Size of our object, useful for things that have physics
|
||||
vec3_t mMin;
|
||||
vec3_t mMax;
|
||||
|
||||
int mImpactFxID; // if we have an impact event, we may have to call an effect
|
||||
int mDeathFxID; // if we have a death event, we may have to call an effect
|
||||
|
||||
miniRefEntity_t mRefEnt;
|
||||
|
||||
int mSoundRadius;
|
||||
int mSoundVolume;
|
||||
|
||||
public:
|
||||
|
||||
CEffect();
|
||||
virtual ~CEffect() {}
|
||||
|
||||
virtual void Die() {}
|
||||
virtual bool Update() { return true; }
|
||||
virtual void Draw(void) {}
|
||||
|
||||
inline miniRefEntity_t &GetRefEnt(void) { return mRefEnt; }
|
||||
|
||||
inline void SetNext(CEffect *Next) { mNext = Next; }
|
||||
inline CEffect *GetNext(void) { return mNext; }
|
||||
inline void GetOrigin(vec3_t dest) {VectorCopy( mOrigin1, dest); }
|
||||
|
||||
inline void SetSTScale(float s,float t) { mRefEnt.shaderTexCoord[0]=s;mRefEnt.shaderTexCoord[1]=t;}
|
||||
|
||||
inline void SetSound ( int vol, int rad) { mSoundRadius = rad; mSoundVolume = vol; }
|
||||
inline void SetMin( vec3_t min ) { if(min){VectorCopy(min,mMin);}else{VectorClear(mMin);} }
|
||||
inline void SetMax( vec3_t max ) { if(max){VectorCopy(max,mMax);}else{VectorClear(mMax);} }
|
||||
inline void SetFlags( int flags ) { mFlags = flags; }
|
||||
inline void AddFlags( int flags ) { mFlags |= flags; }
|
||||
inline void ClearFlags( int flags ) { mFlags &= ~flags; }
|
||||
inline void SetOrigin1( vec3_t org ) { if(org){VectorCopy(org,mOrigin1);}else{VectorClear(mOrigin1);} }
|
||||
inline void SetTimeStart( int time ) { mTimeStart = time; if (mFlags&FX_SET_SHADER_TIME) { mRefEnt.shaderTime = time * 0.001f; }}
|
||||
inline void SetTimeEnd( int time ) { mTimeEnd = time; }
|
||||
inline void SetImpactFxID( int id ) { mImpactFxID = id; }
|
||||
inline void SetDeathFxID( int id ) { mDeathFxID = id; }
|
||||
inline EMatImpactEffect GetMatImpactFX() { return mMatImpactFX; }
|
||||
inline int GetMatImpactParm() { return mMatImpactParm; }
|
||||
inline void SetMatImpactFX(EMatImpactEffect matFX) { mMatImpactFX = matFX; }
|
||||
inline void SetMatImpactParm(int matParm) { mMatImpactParm = matParm; }
|
||||
};
|
||||
|
||||
//---------------------------------------------------
|
||||
// This class is kind of an exception to the "rule".
|
||||
// For now it exists only for allowing an easy way
|
||||
// to get the saber slash trails rendered.
|
||||
//---------------------------------------------------
|
||||
class CTrail : public CEffect
|
||||
{
|
||||
// This is such a specific case thing, just grant public access to the goods.
|
||||
protected:
|
||||
|
||||
void Draw();
|
||||
|
||||
public:
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vec3_t origin;
|
||||
|
||||
// very specifc case, we can modulate the color and the alpha
|
||||
vec3_t rgb;
|
||||
vec3_t destrgb;
|
||||
vec3_t curRGB;
|
||||
|
||||
float alpha;
|
||||
float destAlpha;
|
||||
float curAlpha;
|
||||
|
||||
// this is a very specific case thing...allow interpolating the st coords so we can map the texture
|
||||
// properly as this segement progresses through it's life
|
||||
float ST[2];
|
||||
float destST[2];
|
||||
float curST[2];
|
||||
|
||||
} TVert;
|
||||
|
||||
TVert mVerts[4];
|
||||
qhandle_t mShader;
|
||||
|
||||
|
||||
CTrail() {};
|
||||
virtual ~CTrail() {};
|
||||
|
||||
virtual bool Update();
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
class CLight : public CEffect
|
||||
{
|
||||
protected:
|
||||
|
||||
float mSizeStart;
|
||||
float mSizeEnd;
|
||||
float mSizeParm;
|
||||
|
||||
vec3_t mOrgOffset;
|
||||
vec3_t mRGBStart;
|
||||
vec3_t mRGBEnd;
|
||||
float mRGBParm;
|
||||
|
||||
CGhoul2Info_v mGhoul2;
|
||||
short mEntNum;
|
||||
char mModelNum;
|
||||
char mBoltNum;
|
||||
|
||||
void UpdateSize();
|
||||
void UpdateRGB();
|
||||
|
||||
virtual void Draw(void);
|
||||
public:
|
||||
|
||||
inline CLight(void)
|
||||
{
|
||||
mEntNum = -1; mModelNum = -1; mBoltNum = -1;
|
||||
}
|
||||
|
||||
virtual ~CLight(void)
|
||||
{
|
||||
mGhoul2.kill(); //remove my model ref without actually deleting
|
||||
}
|
||||
|
||||
inline void SetBoltinfo( int iGhoul2, int entNum, int modelNum = -1, int boltNum = -1 )
|
||||
{
|
||||
mGhoul2 = iGhoul2; mEntNum = entNum; mModelNum = modelNum; mBoltNum = boltNum;
|
||||
}
|
||||
|
||||
virtual bool Update();
|
||||
|
||||
inline void SetSizeStart( float sz ) { mSizeStart = sz; }
|
||||
inline void SetSizeEnd( float sz ) { mSizeEnd = sz; }
|
||||
inline void SetSizeParm( float parm ) { mSizeParm = parm; }
|
||||
|
||||
inline void SetOrgOffset( const vec3_t o ) { if(o){VectorCopy(o,mOrgOffset);}else{VectorClear(mOrgOffset);}}
|
||||
inline void SetRGBStart( vec3_t rgb ) { if(rgb){VectorCopy(rgb,mRGBStart);}else{VectorClear(mRGBStart);} }
|
||||
inline void SetRGBEnd( vec3_t rgb ) { if(rgb){VectorCopy(rgb,mRGBEnd);}else{VectorClear(mRGBEnd);} }
|
||||
inline void SetRGBParm( float parm ) { mRGBParm = parm; }
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
class CParticle : public CEffect
|
||||
{
|
||||
protected:
|
||||
|
||||
vec3_t mOrgOffset;
|
||||
|
||||
vec3_t mVel;
|
||||
vec3_t mAccel;
|
||||
|
||||
float mSizeStart;
|
||||
float mSizeEnd;
|
||||
float mSizeParm;
|
||||
|
||||
vec3_t mRGBStart;
|
||||
vec3_t mRGBEnd;
|
||||
float mRGBParm;
|
||||
|
||||
float mAlphaStart;
|
||||
float mAlphaEnd;
|
||||
float mAlphaParm;
|
||||
|
||||
float mRotationDelta;
|
||||
float mElasticity;
|
||||
|
||||
CGhoul2Info_v mGhoul2;
|
||||
short mEntNum;
|
||||
char mModelNum;
|
||||
char mBoltNum;
|
||||
|
||||
bool UpdateOrigin();
|
||||
void UpdateSize();
|
||||
void UpdateRGB();
|
||||
void UpdateAlpha();
|
||||
void UpdateRotation();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
inline void SetBoltinfo( int iGhoul2, int entNum, int modelNum = -1, int boltNum = -1 )
|
||||
{
|
||||
mGhoul2 = iGhoul2; mEntNum = entNum; mModelNum = modelNum; mBoltNum = boltNum;
|
||||
}
|
||||
|
||||
inline CParticle::CParticle(void)
|
||||
{
|
||||
mRefEnt.reType = RT_SPRITE; mEntNum = -1; mModelNum = -1; mBoltNum = -1;
|
||||
}
|
||||
|
||||
virtual CParticle::~CParticle(void)
|
||||
{
|
||||
mGhoul2.kill(); //remove my model ref without actually deleting
|
||||
}
|
||||
|
||||
|
||||
virtual void Init();
|
||||
virtual void Die();
|
||||
virtual bool Update();
|
||||
virtual bool Cull(void);
|
||||
virtual void Draw(void);
|
||||
|
||||
inline void SetShader( qhandle_t sh ) { mRefEnt.customShader = sh; }
|
||||
|
||||
inline void SetOrgOffset( const vec3_t o ) { if(o){VectorCopy(o,mOrgOffset);}else{VectorClear(mOrgOffset);}}
|
||||
inline void SetVel( vec3_t vel ) { if(vel){VectorCopy(vel,mVel);}else{VectorClear(mVel);} }
|
||||
inline void SetAccel( vec3_t ac ) { if(ac){VectorCopy(ac,mAccel);}else{VectorClear(mAccel);} }
|
||||
|
||||
inline void SetSizeStart( float sz ) { mSizeStart = sz; mRefEnt.radius = sz; }
|
||||
inline void SetSizeEnd( float sz ) { mSizeEnd = sz; }
|
||||
inline void SetSizeParm( float parm ) { mSizeParm = parm; }
|
||||
|
||||
inline void SetRGBStart( vec3_t rgb ) { if(rgb){VectorCopy(rgb,mRGBStart);}else{VectorClear(mRGBStart);} }
|
||||
inline void SetRGBEnd( vec3_t rgb ) { if(rgb){VectorCopy(rgb,mRGBEnd);}else{VectorClear(mRGBEnd);} }
|
||||
inline void SetRGBParm( float parm ) { mRGBParm = parm; }
|
||||
|
||||
inline void SetAlphaStart( float al ) { mAlphaStart = al; }
|
||||
inline void SetAlphaEnd( float al ) { mAlphaEnd = al; }
|
||||
inline void SetAlphaParm( float parm ) { mAlphaParm = parm; }
|
||||
|
||||
inline void SetRotation( float rot ) { mRefEnt.rotation = rot; }
|
||||
inline void SetRotationDelta( float rot ) { mRotationDelta = rot; }
|
||||
inline void SetElasticity( float el ) { mElasticity = el; }
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
class CFlash : public CParticle
|
||||
{
|
||||
public:
|
||||
|
||||
CFlash():
|
||||
mScreenX(0),
|
||||
mScreenY(0),
|
||||
mRadiusModifier(1)
|
||||
{}
|
||||
|
||||
virtual ~CFlash() {}
|
||||
|
||||
virtual bool Update();
|
||||
virtual void Draw(void);
|
||||
virtual bool Cull(void) { return false; }
|
||||
|
||||
void Init( void );
|
||||
|
||||
protected:
|
||||
// kef -- mScreenX and mScreenY are used for flashes that are FX_LOCALIZED_FLASH
|
||||
float mScreenX;
|
||||
float mScreenY;
|
||||
float mRadiusModifier;
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
class CLine : public CParticle
|
||||
{
|
||||
protected:
|
||||
|
||||
vec3_t mOrigin2;
|
||||
|
||||
virtual void Draw(void);
|
||||
public:
|
||||
|
||||
CLine();
|
||||
virtual ~CLine() {}
|
||||
|
||||
virtual void Die() {}
|
||||
|
||||
virtual bool Update();
|
||||
|
||||
inline void SetOrigin2( vec3_t org2 ) { VectorCopy( org2, mOrigin2 ); }
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
class CBezier : public CLine
|
||||
{
|
||||
protected:
|
||||
|
||||
vec3_t mControl1;
|
||||
vec3_t mControl1Vel;
|
||||
|
||||
vec3_t mControl2;
|
||||
vec3_t mControl2Vel;
|
||||
|
||||
bool mInit;
|
||||
|
||||
public:
|
||||
|
||||
CBezier(){ mInit = false; }
|
||||
virtual ~CBezier() {}
|
||||
|
||||
virtual void Die() {}
|
||||
virtual bool Update();
|
||||
virtual bool Cull(void);
|
||||
virtual void Draw(void);
|
||||
|
||||
void DrawSegment( vec3_t start, vec3_t end, float texcoord1, float texcoord2, float segPercent, float lastSegPercent );
|
||||
|
||||
inline void SetControlPoints( vec3_t ctrl1, vec3_t ctrl2 ) { VectorCopy( ctrl1, mControl1 ); VectorCopy( ctrl2, mControl2 ); }
|
||||
inline void SetControlVel( vec3_t ctrl1v, vec3_t ctrl2v ) { VectorCopy( ctrl1v, mControl1Vel ); VectorCopy( ctrl2v, mControl2Vel ); }
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
class CElectricity : public CLine
|
||||
{
|
||||
protected:
|
||||
|
||||
float mChaos;
|
||||
|
||||
virtual void Draw(void);
|
||||
public:
|
||||
|
||||
CElectricity();
|
||||
virtual ~CElectricity() {}
|
||||
|
||||
virtual void Die() {}
|
||||
|
||||
virtual bool Update();
|
||||
|
||||
void Initialize();
|
||||
|
||||
inline void SetChaos( float chaos ) { mChaos = chaos; }
|
||||
};
|
||||
|
||||
|
||||
// Oriented quad
|
||||
//------------------------------
|
||||
class COrientedParticle : public CParticle
|
||||
{
|
||||
protected:
|
||||
|
||||
vec3_t mNormal;
|
||||
|
||||
public:
|
||||
|
||||
COrientedParticle();
|
||||
virtual ~COrientedParticle() {}
|
||||
|
||||
virtual bool Update();
|
||||
virtual bool Cull(void);
|
||||
virtual void Draw(void);
|
||||
|
||||
inline void SetNormal( vec3_t norm ) { VectorCopy( norm, mNormal ); }
|
||||
};
|
||||
|
||||
//------------------------------
|
||||
class CTail : public CParticle
|
||||
{
|
||||
protected:
|
||||
|
||||
vec3_t mOldOrigin;
|
||||
|
||||
float mLengthStart;
|
||||
float mLengthEnd;
|
||||
float mLengthParm;
|
||||
|
||||
float mLength;
|
||||
|
||||
void UpdateLength();
|
||||
void CalcNewEndpoint();
|
||||
|
||||
virtual void Draw(void);
|
||||
public:
|
||||
|
||||
CTail();
|
||||
virtual ~CTail() {}
|
||||
|
||||
virtual bool Update();
|
||||
|
||||
inline void SetLengthStart( float len ) { mLengthStart = len; }
|
||||
inline void SetLengthEnd( float len ) { mLengthEnd = len; }
|
||||
inline void SetLengthParm( float len ) { mLengthParm = len; }
|
||||
};
|
||||
|
||||
|
||||
//------------------------------
|
||||
class CCylinder : public CTail
|
||||
{
|
||||
protected:
|
||||
|
||||
float mSize2Start;
|
||||
float mSize2End;
|
||||
float mSize2Parm;
|
||||
qboolean mTraceEnd;
|
||||
|
||||
void UpdateSize2();
|
||||
|
||||
virtual void Draw(void);
|
||||
public:
|
||||
|
||||
CCylinder();
|
||||
virtual ~CCylinder() {}
|
||||
|
||||
virtual bool Cull(void);
|
||||
virtual void UpdateLength(void);
|
||||
virtual bool Update();
|
||||
|
||||
inline void SetSize2Start( float sz ) { mSize2Start = sz; }
|
||||
inline void SetSize2End( float sz ) { mSize2End = sz; }
|
||||
inline void SetSize2Parm( float parm ) { mSize2Parm = parm; }
|
||||
inline void SetTraceEnd(qboolean traceEnd) { mTraceEnd = traceEnd; }
|
||||
|
||||
inline void SetNormal( vec3_t norm ) { VectorCopy( norm, mRefEnt.axis[0] ); }
|
||||
};
|
||||
|
||||
|
||||
//------------------------------
|
||||
// Emitters are derived from particles because, although they don't draw, any effect called
|
||||
// from them can borrow an initial or ending value from the emitters current alpha, rgb, etc..
|
||||
class CEmitter : public CParticle
|
||||
{
|
||||
protected:
|
||||
|
||||
vec3_t mOldOrigin; // we use these to do some nice
|
||||
vec3_t mLastOrigin; // tricks...
|
||||
vec3_t mOldVelocity; //
|
||||
int mOldTime;
|
||||
|
||||
vec3_t mAngles; // for a rotating thing, using a delta
|
||||
vec3_t mAngleDelta; // as opposed to an end angle is probably much easier
|
||||
|
||||
int mEmitterFxID; // if we have emitter fx, this is our id
|
||||
|
||||
float mDensity; // controls how often emitter chucks an effect
|
||||
float mVariance; // density sloppiness
|
||||
|
||||
void UpdateAngles();
|
||||
|
||||
virtual void Draw(void);
|
||||
public:
|
||||
|
||||
CEmitter();
|
||||
virtual ~CEmitter();
|
||||
|
||||
virtual bool Cull(void) {return false;}
|
||||
virtual bool Update();
|
||||
|
||||
inline void SetModel( qhandle_t model ) { mRefEnt.hModel = model; }
|
||||
inline void SetAngles( vec3_t ang ) { if(ang){VectorCopy(ang,mAngles);}else{VectorClear(mAngles);} }
|
||||
inline void SetAngleDelta( vec3_t ang ) { if(ang){VectorCopy(ang,mAngleDelta);}else{VectorClear(mAngleDelta);} }
|
||||
inline void SetEmitterFxID( int id ) { mEmitterFxID = id; }
|
||||
inline void SetDensity( float density ) { mDensity = density; }
|
||||
inline void SetVariance( float var ) { mVariance = var; }
|
||||
inline void SetOldTime( int time ) { mOldTime = time; }
|
||||
inline void SetLastOrg( vec3_t org ) { if(org){VectorCopy(org,mLastOrigin);}else{VectorClear(mLastOrigin);} }
|
||||
inline void SetLastVel( vec3_t vel ) { if(vel){VectorCopy(vel,mOldVelocity);}else{VectorClear(mOldVelocity);} }
|
||||
};
|
||||
|
||||
// We're getting pretty low level here, not the kind of thing to abuse considering how much overhead this
|
||||
// adds to a SINGLE triangle or quad....
|
||||
//------------------------------
|
||||
#define MAX_CPOLY_VERTS 5
|
||||
|
||||
class CPoly : public CParticle
|
||||
{
|
||||
protected:
|
||||
|
||||
int mCount;
|
||||
vec3_t mRotDelta;
|
||||
int mTimeStamp;
|
||||
|
||||
public:
|
||||
|
||||
vec3_t mOrg[MAX_CPOLY_VERTS];
|
||||
vec2_t mST[MAX_CPOLY_VERTS];
|
||||
|
||||
float mRot[3][3];
|
||||
int mLastFrameTime;
|
||||
|
||||
|
||||
CPoly() {}
|
||||
virtual ~CPoly() {}
|
||||
|
||||
virtual bool Update();
|
||||
virtual bool Cull(void);
|
||||
virtual void Draw(void);
|
||||
|
||||
void PolyInit();
|
||||
void CalcRotateMatrix();
|
||||
void Rotate();
|
||||
|
||||
inline void SetNumVerts( int c ) { mCount = c; }
|
||||
inline void SetRot( vec3_t r ) { if(r){VectorCopy(r,mRotDelta);}else{VectorClear(mRotDelta);}}
|
||||
inline void SetMotionTimeStamp( int t ) { mTimeStamp = theFxHelper.GetTime() + t; }
|
||||
inline int GetMotionTimeStamp() { return mTimeStamp; }
|
||||
};
|
||||
|
||||
|
||||
#endif //FX_PRIMITIVES_H_INC
|
||||
1774
codemp/client/fxscheduler.cpp
Normal file
1774
codemp/client/fxscheduler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
505
codemp/client/fxscheduler.h
Normal file
505
codemp/client/fxscheduler.h
Normal file
@@ -0,0 +1,505 @@
|
||||
|
||||
#if !defined(FX_UTIL_H_INC)
|
||||
#include "FxUtil.h"
|
||||
#endif
|
||||
|
||||
#if !defined(GENERICPARSER2_H_INC)
|
||||
#include "../qcommon/GenericParser2.h"
|
||||
#endif
|
||||
|
||||
#ifndef FX_SCHEDULER_H_INC
|
||||
#define FX_SCHEDULER_H_INC
|
||||
|
||||
#pragma warning (push, 3) //go back down to 3 for the stl include
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#pragma warning (pop)
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
#define FX_FILE_PATH "effects"
|
||||
|
||||
#define FX_MAX_TRACE_DIST 16384 // SOF2 uses a larger scale
|
||||
#define FX_MAX_EFFECTS 256 // how many effects the system can store
|
||||
#define FX_MAX_2DEFFECTS 64 // how many 2d effects the system can store
|
||||
#define FX_MAX_EFFECT_COMPONENTS 24 // how many primitives an effect can hold, this should be plenty
|
||||
#define FX_MAX_PRIM_NAME 32
|
||||
|
||||
//-----------------------------------------------
|
||||
// These are spawn flags for primitiveTemplates
|
||||
//-----------------------------------------------
|
||||
|
||||
#define FX_ORG_ON_SPHERE 0x00001 // Pretty dang expensive, calculates a point on a sphere/ellipsoid
|
||||
#define FX_AXIS_FROM_SPHERE 0x00002 // Can be used in conjunction with org_on_sphere to cause particles to move out
|
||||
// from the center of the sphere
|
||||
#define FX_ORG_ON_CYLINDER 0x00004 // calculate point on cylinder/disk
|
||||
|
||||
#define FX_ORG2_FROM_TRACE 0x00010
|
||||
#define FX_TRACE_IMPACT_FX 0x00020 // if trace impacts, we should play one of the specified impact fx files
|
||||
#define FX_ORG2_IS_OFFSET 0x00040 // template specified org2 should be the offset from a trace endpos or
|
||||
// passed in org2. You might use this to lend a random flair to the endpos.
|
||||
// Note: this is done pre-trace, so you may have to specify large numbers for this
|
||||
|
||||
#define FX_CHEAP_ORG_CALC 0x00100 // Origin is calculated relative to passed in axis unless this is on.
|
||||
#define FX_CHEAP_ORG2_CALC 0x00200 // Origin2 is calculated relative to passed in axis unless this is on.
|
||||
#define FX_VEL_IS_ABSOLUTE 0x00400 // Velocity isn't relative to passed in axis with this flag on.
|
||||
#define FX_ACCEL_IS_ABSOLUTE 0x00800 // Acceleration isn't relative to passed in axis with this flag on.
|
||||
|
||||
#define FX_RAND_ROT_AROUND_FWD 0x01000 // Randomly rotates up and right around forward vector
|
||||
#define FX_EVEN_DISTRIBUTION 0x02000 // When you have a delay, it normally picks a random time to play. When
|
||||
// this flag is on, it generates an even time distribution
|
||||
#define FX_RGB_COMPONENT_INTERP 0x04000 // Picks a color on the line defined by RGB min & max, default is to pick color in cube defined by min & max
|
||||
|
||||
#define FX_AFFECTED_BY_WIND 0x10000 // this effect primitive needs to query wind
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//
|
||||
// CMediaHandles
|
||||
//
|
||||
// Primitive templates might want to use a list of sounds, shaders
|
||||
// or models to get a bit more variation in their effects.
|
||||
//
|
||||
//-----------------------------------------------------------------
|
||||
class CMediaHandles
|
||||
{
|
||||
private:
|
||||
|
||||
vector<int> mMediaList;
|
||||
|
||||
public:
|
||||
|
||||
void AddHandle( int item ) { mMediaList.push_back( item ); }
|
||||
int GetHandle() { if (mMediaList.size()==0) {return 0;}
|
||||
else {return mMediaList[irand(0,mMediaList.size()-1)];} }
|
||||
|
||||
void operator=(const CMediaHandles &that );
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//
|
||||
// CFxRange
|
||||
//
|
||||
// Primitive templates typically use this class to define each of
|
||||
// its members. This is done to make it easier to create effects
|
||||
// with a desired range of characteristics.
|
||||
//
|
||||
//-----------------------------------------------------------------
|
||||
class CFxRange
|
||||
{
|
||||
private:
|
||||
|
||||
float mMin;
|
||||
float mMax;
|
||||
|
||||
public:
|
||||
|
||||
CFxRange(void) { mMin = 0.0f; mMax = 0.0f; }
|
||||
|
||||
inline void SetRange(float min,float max) { mMin = min; mMax = max; }
|
||||
|
||||
inline float GetMax(void) const { return mMax; }
|
||||
inline float GetMin(void) const { return mMin; }
|
||||
inline float GetVal(float fraction) const { if(mMin != mMax) { return mMin + fraction * (mMax - mMin); } else { return mMin; } }
|
||||
inline float GetVal(void) const { if(mMin != mMax) { return flrand(mMin,mMax); } else { return mMin; } }
|
||||
|
||||
inline int GetRoundedVal() const {if(mMin == mMax){return (int)mMin;}
|
||||
return (int)(flrand(mMin, mMax) + 0.5f);}
|
||||
|
||||
bool operator==(const CFxRange &rhs) const { return ((mMin == rhs.mMin) && (mMax == rhs.mMax)); }
|
||||
};
|
||||
|
||||
|
||||
//----------------------------
|
||||
// Supported primitive types
|
||||
//----------------------------
|
||||
|
||||
enum EPrimType
|
||||
{
|
||||
None = 0,
|
||||
Particle, // sprite
|
||||
Line,
|
||||
Tail, // comet-like tail thing
|
||||
Cylinder,
|
||||
Emitter, // emits effects as it moves, can also attach a chunk
|
||||
Sound,
|
||||
Decal, // projected onto architecture
|
||||
OrientedParticle,
|
||||
Electricity,
|
||||
FxRunner,
|
||||
Light,
|
||||
CameraShake,
|
||||
ScreenFlash
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//
|
||||
// CPrimitiveTemplate
|
||||
//
|
||||
// The primitive template is used to spawn 1 or more fx primitives
|
||||
// with the range of characteristics defined by the template.
|
||||
//
|
||||
// As such, I just made this one huge shared class knowing that
|
||||
// there won't be many of them in memory at once, and we won't
|
||||
// be dynamically creating and deleting them mid-game. Also,
|
||||
// note that not every primitive type will use all of these fields.
|
||||
//
|
||||
//-----------------------------------------------------------------
|
||||
class CPrimitiveTemplate
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// These kinds of things should not even be allowed to be accessed publicly
|
||||
bool mCopy;
|
||||
int mRefCount; // For a copy of a primitive...when we figure out how many items we want to spawn,
|
||||
// we'll store that here and then decrement us for each we actually spawn. When we
|
||||
// hit zero, we are no longer used and so we can just free ourselves
|
||||
|
||||
char mName[FX_MAX_PRIM_NAME];
|
||||
|
||||
EPrimType mType;
|
||||
|
||||
CFxRange mSpawnDelay;
|
||||
CFxRange mSpawnCount;
|
||||
CFxRange mLife;
|
||||
int mCullRange;
|
||||
|
||||
CMediaHandles mMediaHandles;
|
||||
CMediaHandles mImpactFxHandles;
|
||||
CMediaHandles mDeathFxHandles;
|
||||
CMediaHandles mEmitterFxHandles;
|
||||
CMediaHandles mPlayFxHandles;
|
||||
|
||||
int mFlags; // These need to get passed on to the primitive
|
||||
int mSpawnFlags; // These are only used to control spawning, but never get passed to prims.
|
||||
|
||||
EMatImpactEffect mMatImpactFX;
|
||||
|
||||
vec3_t mMin;
|
||||
vec3_t mMax;
|
||||
|
||||
CFxRange mOrigin1X;
|
||||
CFxRange mOrigin1Y;
|
||||
CFxRange mOrigin1Z;
|
||||
|
||||
CFxRange mOrigin2X;
|
||||
CFxRange mOrigin2Y;
|
||||
CFxRange mOrigin2Z;
|
||||
|
||||
CFxRange mRadius; // spawn on sphere/ellipse/disk stuff.
|
||||
CFxRange mHeight;
|
||||
CFxRange mWindModifier;
|
||||
|
||||
CFxRange mRotation;
|
||||
CFxRange mRotationDelta;
|
||||
|
||||
CFxRange mAngle1;
|
||||
CFxRange mAngle2;
|
||||
CFxRange mAngle3;
|
||||
|
||||
CFxRange mAngle1Delta;
|
||||
CFxRange mAngle2Delta;
|
||||
CFxRange mAngle3Delta;
|
||||
|
||||
CFxRange mVelX;
|
||||
CFxRange mVelY;
|
||||
CFxRange mVelZ;
|
||||
|
||||
CFxRange mAccelX;
|
||||
CFxRange mAccelY;
|
||||
CFxRange mAccelZ;
|
||||
|
||||
CFxRange mGravity;
|
||||
|
||||
CFxRange mDensity;
|
||||
CFxRange mVariance;
|
||||
|
||||
CFxRange mRedStart;
|
||||
CFxRange mGreenStart;
|
||||
CFxRange mBlueStart;
|
||||
|
||||
CFxRange mRedEnd;
|
||||
CFxRange mGreenEnd;
|
||||
CFxRange mBlueEnd;
|
||||
|
||||
CFxRange mRGBParm;
|
||||
|
||||
CFxRange mAlphaStart;
|
||||
CFxRange mAlphaEnd;
|
||||
CFxRange mAlphaParm;
|
||||
|
||||
CFxRange mSizeStart;
|
||||
CFxRange mSizeEnd;
|
||||
CFxRange mSizeParm;
|
||||
|
||||
CFxRange mSize2Start;
|
||||
CFxRange mSize2End;
|
||||
CFxRange mSize2Parm;
|
||||
|
||||
CFxRange mLengthStart;
|
||||
CFxRange mLengthEnd;
|
||||
CFxRange mLengthParm;
|
||||
|
||||
CFxRange mTexCoordS;
|
||||
CFxRange mTexCoordT;
|
||||
|
||||
CFxRange mElasticity;
|
||||
|
||||
int mSoundRadius;
|
||||
int mSoundVolume;
|
||||
|
||||
// Lower level parsing utilities
|
||||
bool ParseVector( const char *val, vec3_t min, vec3_t max );
|
||||
bool ParseFloat( const char *val, float *min, float *max );
|
||||
bool ParseGroupFlags( const char *val, int *flags );
|
||||
|
||||
// Base key processing
|
||||
// Note that these all have their own parse functions in case it becomes important to do certain kinds
|
||||
// of validation specific to that type.
|
||||
bool ParseMin( const char *val );
|
||||
bool ParseMax( const char *val );
|
||||
bool ParseDelay( const char *val );
|
||||
bool ParseCount( const char *val );
|
||||
bool ParseLife( const char *val );
|
||||
bool ParseElasticity( const char *val );
|
||||
bool ParseFlags( const char *val );
|
||||
bool ParseSpawnFlags( const char *val );
|
||||
|
||||
bool ParseOrigin1( const char *val );
|
||||
bool ParseOrigin2( const char *val );
|
||||
bool ParseRadius( const char *val );
|
||||
bool ParseHeight( const char *val );
|
||||
bool ParseWindModifier( const char *val );
|
||||
bool ParseRotation( const char *val );
|
||||
bool ParseRotationDelta( const char *val );
|
||||
bool ParseAngle( const char *val );
|
||||
bool ParseAngleDelta( const char *val );
|
||||
bool ParseVelocity( const char *val );
|
||||
bool ParseAcceleration( const char *val );
|
||||
bool ParseGravity( const char *val );
|
||||
bool ParseDensity( const char *val );
|
||||
bool ParseVariance( const char *val );
|
||||
|
||||
// Group type processing
|
||||
bool ParseRGB( CGPGroup *grp );
|
||||
bool ParseAlpha( CGPGroup *grp );
|
||||
bool ParseSize( CGPGroup *grp );
|
||||
bool ParseSize2( CGPGroup *grp );
|
||||
bool ParseLength( CGPGroup *grp );
|
||||
|
||||
bool ParseModels( CGPValue *grp );
|
||||
bool ParseShaders( CGPValue *grp );
|
||||
bool ParseSounds( CGPValue *grp );
|
||||
|
||||
bool ParseImpactFxStrings( CGPValue *grp );
|
||||
bool ParseDeathFxStrings( CGPValue *grp );
|
||||
bool ParseEmitterFxStrings( CGPValue *grp );
|
||||
bool ParsePlayFxStrings( CGPValue *grp );
|
||||
|
||||
// Group keys
|
||||
bool ParseRGBStart( const char *val );
|
||||
bool ParseRGBEnd( const char *val );
|
||||
bool ParseRGBParm( const char *val );
|
||||
bool ParseRGBFlags( const char *val );
|
||||
|
||||
bool ParseAlphaStart( const char *val );
|
||||
bool ParseAlphaEnd( const char *val );
|
||||
bool ParseAlphaParm( const char *val );
|
||||
bool ParseAlphaFlags( const char *val );
|
||||
|
||||
bool ParseSizeStart( const char *val );
|
||||
bool ParseSizeEnd( const char *val );
|
||||
bool ParseSizeParm( const char *val );
|
||||
bool ParseSizeFlags( const char *val );
|
||||
|
||||
bool ParseSize2Start( const char *val );
|
||||
bool ParseSize2End( const char *val );
|
||||
bool ParseSize2Parm( const char *val );
|
||||
bool ParseSize2Flags( const char *val );
|
||||
|
||||
bool ParseLengthStart( const char *val );
|
||||
bool ParseLengthEnd( const char *val );
|
||||
bool ParseLengthParm( const char *val );
|
||||
bool ParseLengthFlags( const char *val );
|
||||
|
||||
bool ParseMaterialImpact(const char *val);
|
||||
|
||||
public:
|
||||
|
||||
CPrimitiveTemplate();
|
||||
~CPrimitiveTemplate() {};
|
||||
|
||||
bool ParsePrimitive( CGPGroup *grp );
|
||||
|
||||
void operator=(const CPrimitiveTemplate &that);
|
||||
};
|
||||
|
||||
// forward declaration
|
||||
struct SEffectTemplate;
|
||||
|
||||
// Effects are built of one or more primitives
|
||||
struct SEffectTemplate
|
||||
{
|
||||
bool mInUse;
|
||||
bool mCopy;
|
||||
char mEffectName[MAX_QPATH]; // is this extraneous??
|
||||
int mPrimitiveCount;
|
||||
int mRepeatDelay;
|
||||
CPrimitiveTemplate *mPrimitives[FX_MAX_EFFECT_COMPONENTS];
|
||||
|
||||
bool operator == (const char * name) const
|
||||
{
|
||||
return !stricmp( mEffectName, name );
|
||||
}
|
||||
void operator=(const SEffectTemplate &that);
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
//
|
||||
// CFxScheduler
|
||||
//
|
||||
// The scheduler not only handles requests to play an effect, it
|
||||
// tracks the request throughout its life if necessary, creating
|
||||
// any of the delayed components as needed.
|
||||
//
|
||||
//-----------------------------------------------------------------
|
||||
class CFxScheduler
|
||||
{
|
||||
private:
|
||||
|
||||
// We hold a scheduled effect here
|
||||
struct SScheduledEffect
|
||||
{
|
||||
CPrimitiveTemplate *mpTemplate; // primitive template
|
||||
int mStartTime;
|
||||
char mModelNum; // uset to determine which ghoul2 model we want to bolt this effect to
|
||||
char mBoltNum; // used to determine which bolt on the ghoul2 model we should be attaching this effect to
|
||||
short mEntNum; // used to determine which entity this ghoul model is attached to.
|
||||
bool mPortalEffect; // rww - render this before skyportals, and not in the normal world view.
|
||||
bool mIsRelative; // bolt this puppy on keep it updated
|
||||
int iGhoul2;
|
||||
vec3_t mOrigin;
|
||||
vec3_t mAxis[3];
|
||||
|
||||
bool operator <= (const int time) const
|
||||
{
|
||||
return mStartTime <= time;
|
||||
}
|
||||
};
|
||||
|
||||
/* Looped Effects get stored and reschedule at mRepeatRate */
|
||||
#define MAX_LOOPED_FX 32
|
||||
// We hold a looped effect here
|
||||
struct SLoopedEffect
|
||||
{
|
||||
int mId; // effect id
|
||||
int mBoltInfo; // used to determine which bolt on the ghoul2 model we should be attaching this effect to
|
||||
CGhoul2Info_v mGhoul2;
|
||||
int mNextTime; //time to render again
|
||||
int mLoopStopTime; //time to die
|
||||
bool mPortalEffect; // rww - render this before skyportals, and not in the normal world view.
|
||||
bool mIsRelative; // bolt this puppy on keep it updated
|
||||
};
|
||||
|
||||
SLoopedEffect mLoopedEffectArray[MAX_LOOPED_FX];
|
||||
|
||||
int ScheduleLoopedEffect( int id, int boltInfo, int iGhoul2, bool isPortal, int iLoopTime, bool isRelative );
|
||||
void AddLoopedEffects( );
|
||||
|
||||
|
||||
class CScheduled2DEffect
|
||||
{
|
||||
public:
|
||||
CScheduled2DEffect():
|
||||
mScreenX(0),
|
||||
mScreenY(0),
|
||||
mWidth(0),
|
||||
mHeight(0),
|
||||
mShaderHandle(0)
|
||||
{mColor[0]=mColor[1]=mColor[2]=mColor[3]=1.0f;}
|
||||
|
||||
public:
|
||||
float mScreenX;
|
||||
float mScreenY;
|
||||
float mWidth;
|
||||
float mHeight;
|
||||
vec4_t mColor; // bytes A, G, B, R -- see class paletteRGBA_c
|
||||
qhandle_t mShaderHandle;
|
||||
};
|
||||
|
||||
// this makes looking up the index based on the string name much easier
|
||||
typedef map<string, int> TEffectID;
|
||||
|
||||
typedef list<SScheduledEffect*> TScheduledEffect;
|
||||
|
||||
// Effects
|
||||
SEffectTemplate mEffectTemplates[FX_MAX_EFFECTS];
|
||||
TEffectID mEffectIDs; // if you only have the unique effect name, you'll have to use this to get the ID.
|
||||
|
||||
// 2D effects
|
||||
CScheduled2DEffect m2DEffects[FX_MAX_2DEFFECTS];
|
||||
int mNextFree2DEffect;
|
||||
|
||||
// List of scheduled effects that will need to be created at the correct time.
|
||||
TScheduledEffect mFxSchedule;
|
||||
|
||||
|
||||
// Private function prototypes
|
||||
SEffectTemplate *GetNewEffectTemplate( int *id, const char *file );
|
||||
|
||||
void AddPrimitiveToEffect( SEffectTemplate *fx, CPrimitiveTemplate *prim );
|
||||
int ParseEffect( const char *file, CGPGroup *base );
|
||||
|
||||
void CreateEffect( CPrimitiveTemplate *fx, const vec3_t origin, vec3_t axis[3], int lateTime, int fxParm = -1, int iGhoul2 = 0, int entNum = -1, int modelNum = -1, int boltNum = -1);
|
||||
void CreateEffect( CPrimitiveTemplate *fx, SScheduledEffect *schedFx );
|
||||
|
||||
public:
|
||||
|
||||
CFxScheduler();
|
||||
|
||||
int RegisterEffect( const char *file, bool bHasCorrectPath = false ); // handles pre-caching
|
||||
|
||||
// Nasty overloaded madness
|
||||
//rww - maybe this should be done differently.. it's more than a bit confusing.
|
||||
//Remind me when I don't have 50 files checked out.
|
||||
void PlayEffect( int id, vec3_t org, vec3_t fwd, int vol = -1, int rad = -1, bool isPortal = false ); // builds arbitrary perp. right vector, does a cross product to define up
|
||||
void PlayEffect( int id, vec3_t origin, vec3_t axis[3], const int boltInfo=-1, int iGhoul2 = 0,
|
||||
int fxParm = -1, int vol = -1, int rad = -1, bool isPortal = false, int iLoopTime = false, bool isRelative = false );
|
||||
void PlayEffect( const char *file, vec3_t org, int vol = -1, int rad = -1 ); // uses a default up axis
|
||||
void PlayEffect( const char *file, vec3_t org, vec3_t fwd, int vol = -1, int rad = -1 ); // builds arbitrary perp. right vector, does a cross product to define up
|
||||
void PlayEffect( const char *file, vec3_t origin,
|
||||
vec3_t axis[3], const int boltInfo = -1, int iGhoul2 = 0, int fxParm = -1, int vol = -1, int rad = -1, int iLoopTime = false, bool isRelative = false );
|
||||
|
||||
void StopEffect( const char *file, const int boltInfo, bool isPortal = false ); //find a scheduled Looping effect with these parms and kill it
|
||||
void AddScheduledEffects( bool portal ); // call once per CGame frame
|
||||
|
||||
// kef -- called for a 2D effect instead of addRefToScene
|
||||
bool Add2DEffect(float x, float y, float w, float h, vec4_t color, qhandle_t shaderHandle);
|
||||
// kef -- called once per cgame frame AFTER cgi.RenderScene
|
||||
void Draw2DEffects(float screenXScale, float screenYScale);
|
||||
|
||||
int NumScheduledFx() { return mFxSchedule.size(); }
|
||||
void Clean(bool bRemoveTemplates = true, int idToPreserve = 0); // clean out the system
|
||||
|
||||
// FX Override functions
|
||||
SEffectTemplate *GetEffectCopy( int fxHandle, int *newHandle );
|
||||
SEffectTemplate *GetEffectCopy( const char *file, int *newHandle );
|
||||
|
||||
CPrimitiveTemplate *GetPrimitiveCopy( SEffectTemplate *effectCopy, const char *componentName );
|
||||
|
||||
void MaterialImpact(trace_t *tr, CEffect *effect);
|
||||
};
|
||||
|
||||
//-------------------
|
||||
// The one and only
|
||||
//-------------------
|
||||
extern CFxScheduler theFxScheduler;
|
||||
|
||||
#endif // FX_SCHEDULER_H_INC
|
||||
130
codemp/client/fxsystem.cpp
Normal file
130
codemp/client/fxsystem.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
// this include must remain at the top of every CPP file
|
||||
#include "client.h"
|
||||
|
||||
#if !defined(FX_SCHEDULER_H_INC)
|
||||
#include "FxScheduler.h"
|
||||
#endif
|
||||
|
||||
cvar_t *fx_debug;
|
||||
#ifdef _SOF2DEV_
|
||||
cvar_t *fx_freeze;
|
||||
#endif
|
||||
cvar_t *fx_countScale;
|
||||
cvar_t *fx_nearCull;
|
||||
|
||||
#define DEFAULT_EXPLOSION_RADIUS 512
|
||||
|
||||
// Stuff for the FxHelper
|
||||
//------------------------------------------------------
|
||||
SFxHelper::SFxHelper(void) :
|
||||
mTime(0),
|
||||
mOldTime(0),
|
||||
mFrameTime(0),
|
||||
mTimeFrozen(false),
|
||||
refdef(0)
|
||||
{
|
||||
}
|
||||
|
||||
void SFxHelper::ReInit(refdef_t* pRefdef)
|
||||
{
|
||||
mTime = 0;
|
||||
mOldTime = 0;
|
||||
mFrameTime = 0;
|
||||
mTimeFrozen = false;
|
||||
refdef = pRefdef;
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
void SFxHelper::Print( const char *msg, ... )
|
||||
{
|
||||
va_list argptr;
|
||||
char text[1024];
|
||||
|
||||
va_start( argptr, msg );
|
||||
vsprintf( text, msg, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
Com_DPrintf( text );
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
void SFxHelper::AdjustTime( int frametime )
|
||||
{
|
||||
#ifdef _SOF2DEV_
|
||||
if ( fx_freeze->integer || ( frametime <= 0 ))
|
||||
#else
|
||||
if ( frametime <= 0 )
|
||||
#endif
|
||||
{
|
||||
// Allow no time progression when we are paused.
|
||||
mFrameTime = 0;
|
||||
mRealTime = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
mOldTime = mTime;
|
||||
mTime = frametime;
|
||||
mFrameTime = mTime - mOldTime;
|
||||
|
||||
mRealTime = mFrameTime * 0.001f;
|
||||
|
||||
|
||||
/* mFrameTime = frametime;
|
||||
mTime += mFrameTime;
|
||||
mRealTime = mFrameTime * 0.001f;*/
|
||||
|
||||
// mHalfRealTimeSq = mRealTime * mRealTime * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
void SFxHelper::CameraShake( vec3_t origin, float intensity, int radius, int time )
|
||||
{
|
||||
TCGCameraShake *data = (TCGCameraShake *)cl->mSharedMemory;
|
||||
|
||||
VectorCopy(origin, data->mOrigin);
|
||||
data->mIntensity = intensity;
|
||||
data->mRadius = radius;
|
||||
data->mTime = time;
|
||||
|
||||
// VM_Call( cgvm, CG_FX_CAMERASHAKE );
|
||||
//FIXME
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
qboolean SFxHelper::GetOriginAxisFromBolt(CGhoul2Info_v *pGhoul2, int mEntNum, int modelNum, int boltNum, vec3_t /*out*/origin, vec3_t /*out*/axis[3])
|
||||
{
|
||||
qboolean doesBoltExist;
|
||||
mdxaBone_t boltMatrix;
|
||||
TCGGetBoltData *data = (TCGGetBoltData*)cl->mSharedMemory;
|
||||
data->mEntityNum = mEntNum;
|
||||
VM_Call( cgvm, CG_GET_LERP_DATA );//this func will zero out pitch and roll for players, and ridable vehicles
|
||||
|
||||
//Fixme: optimize these VM calls away by storing
|
||||
|
||||
// go away and get me the bolt position for this frame please
|
||||
doesBoltExist = G2API_GetBoltMatrix(*pGhoul2, modelNum, boltNum,
|
||||
&boltMatrix, data->mAngles, data->mOrigin, theFxHelper.mOldTime, 0, data->mScale);
|
||||
|
||||
if (doesBoltExist)
|
||||
{ // set up the axis and origin we need for the actual effect spawning
|
||||
origin[0] = boltMatrix.matrix[0][3];
|
||||
origin[1] = boltMatrix.matrix[1][3];
|
||||
origin[2] = boltMatrix.matrix[2][3];
|
||||
|
||||
axis[1][0] = boltMatrix.matrix[0][0];
|
||||
axis[1][1] = boltMatrix.matrix[1][0];
|
||||
axis[1][2] = boltMatrix.matrix[2][0];
|
||||
|
||||
axis[0][0] = boltMatrix.matrix[0][1];
|
||||
axis[0][1] = boltMatrix.matrix[1][1];
|
||||
axis[0][2] = boltMatrix.matrix[2][1];
|
||||
|
||||
axis[2][0] = boltMatrix.matrix[0][2];
|
||||
axis[2][1] = boltMatrix.matrix[1][2];
|
||||
axis[2][2] = boltMatrix.matrix[2][2];
|
||||
}
|
||||
return doesBoltExist;
|
||||
}
|
||||
226
codemp/client/fxsystem.h
Normal file
226
codemp/client/fxsystem.h
Normal file
@@ -0,0 +1,226 @@
|
||||
|
||||
#ifndef FX_SYSTEM_H_INC
|
||||
#define FX_SYSTEM_H_INC
|
||||
|
||||
#if !defined(G2_H_INC)
|
||||
#include "../ghoul2/G2.h"
|
||||
#include "../ghoul2/G2_local.h"
|
||||
#endif
|
||||
|
||||
extern cvar_t *fx_debug;
|
||||
|
||||
#ifdef _SOF2DEV_
|
||||
extern cvar_t *fx_freeze;
|
||||
#endif
|
||||
|
||||
extern cvar_t *fx_countScale;
|
||||
extern cvar_t *fx_nearCull;
|
||||
|
||||
inline void Vector2Clear(vec2_t a)
|
||||
{
|
||||
a[0] = 0.0f;
|
||||
a[1] = 0.0f;
|
||||
}
|
||||
|
||||
inline void Vector2Set(vec2_t a,float b,float c)
|
||||
{
|
||||
a[0] = b;
|
||||
a[1] = c;
|
||||
}
|
||||
|
||||
inline void Vector2Copy(vec2_t src,vec2_t dst)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
}
|
||||
|
||||
inline void Vector2MA(vec2_t src, float m, vec2_t v, vec2_t dst)
|
||||
{
|
||||
dst[0] = src[0] + (m*v[0]);
|
||||
dst[1] = src[1] + (m*v[1]);
|
||||
}
|
||||
|
||||
inline void Vector2Scale(vec2_t src,float b,vec2_t dst)
|
||||
{
|
||||
dst[0] = src[0] * b;
|
||||
dst[1] = src[1] * b;
|
||||
}
|
||||
|
||||
class SFxHelper
|
||||
{
|
||||
public:
|
||||
int mTime;
|
||||
int mOldTime;
|
||||
int mFrameTime;
|
||||
bool mTimeFrozen;
|
||||
float mRealTime;
|
||||
refdef_t* refdef;
|
||||
#ifdef _DEBUG
|
||||
int mMainRefs;
|
||||
int mMiniRefs;
|
||||
#endif
|
||||
|
||||
public:
|
||||
SFxHelper(void);
|
||||
|
||||
inline int GetTime(void) { return mTime; }
|
||||
inline int GetFrameTime(void) { return mFrameTime; }
|
||||
|
||||
void ReInit(refdef_t* pRefdef);
|
||||
void AdjustTime( int time );
|
||||
|
||||
// These functions are wrapped and used by the fx system in case it makes things a bit more portable
|
||||
void Print( const char *msg, ... );
|
||||
|
||||
// File handling
|
||||
inline int OpenFile( const char *path, fileHandle_t *fh, int mode )
|
||||
{
|
||||
return FS_FOpenFileByMode( path, fh, FS_READ );
|
||||
}
|
||||
inline int ReadFile( void *data, int len, fileHandle_t fh )
|
||||
{
|
||||
FS_Read2( data, len, fh );
|
||||
return 1;
|
||||
}
|
||||
inline void CloseFile( fileHandle_t fh )
|
||||
{
|
||||
FS_FCloseFile( fh );
|
||||
}
|
||||
|
||||
// Sound
|
||||
inline void PlaySound( vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfxHandle, int volume, int radius )
|
||||
{
|
||||
//S_StartSound( origin, ENTITYNUM_NONE, CHAN_AUTO, sfxHandle, volume, radius );
|
||||
S_StartSound( origin, ENTITYNUM_NONE, CHAN_AUTO, sfxHandle );
|
||||
}
|
||||
inline void PlayLocalSound(sfxHandle_t sfxHandle, int entchannel)
|
||||
{
|
||||
//S_StartSound( origin, ENTITYNUM_NONE, CHAN_AUTO, sfxHandle, volume, radius );
|
||||
S_StartLocalSound(sfxHandle, entchannel);
|
||||
}
|
||||
inline int RegisterSound( const char *sound )
|
||||
{
|
||||
return S_RegisterSound( sound );
|
||||
}
|
||||
|
||||
// Physics/collision
|
||||
inline void Trace( trace_t &tr, vec3_t start, vec3_t min, vec3_t max, vec3_t end, int skipEntNum, int flags )
|
||||
{
|
||||
TCGTrace *td = (TCGTrace *)cl->mSharedMemory;
|
||||
|
||||
if ( !min )
|
||||
{
|
||||
min = vec3_origin;
|
||||
}
|
||||
|
||||
if ( !max )
|
||||
{
|
||||
max = vec3_origin;
|
||||
}
|
||||
|
||||
// MATT - what was this?
|
||||
// memset(td, sizeof(*td), 0);
|
||||
memset(td, 0, sizeof(*td));
|
||||
|
||||
VectorCopy(start, td->mStart);
|
||||
VectorCopy(min, td->mMins);
|
||||
VectorCopy(max, td->mMaxs);
|
||||
VectorCopy(end, td->mEnd);
|
||||
td->mSkipNumber = skipEntNum;
|
||||
td->mMask = flags;
|
||||
|
||||
VM_Call( cgvm, CG_TRACE );
|
||||
|
||||
tr = td->mResult;
|
||||
}
|
||||
|
||||
inline void G2Trace( trace_t &tr, vec3_t start, vec3_t min, vec3_t max, vec3_t end, int skipEntNum, int flags )
|
||||
{
|
||||
TCGTrace *td = (TCGTrace *)cl->mSharedMemory;
|
||||
|
||||
if ( !min )
|
||||
{
|
||||
min = vec3_origin;
|
||||
}
|
||||
|
||||
if ( !max )
|
||||
{
|
||||
max = vec3_origin;
|
||||
}
|
||||
|
||||
memset(td, sizeof(*td), 0);
|
||||
VectorCopy(start, td->mStart);
|
||||
VectorCopy(min, td->mMins);
|
||||
VectorCopy(max, td->mMaxs);
|
||||
VectorCopy(end, td->mEnd);
|
||||
td->mSkipNumber = skipEntNum;
|
||||
td->mMask = flags;
|
||||
|
||||
VM_Call( cgvm, CG_G2TRACE );
|
||||
|
||||
tr = td->mResult;
|
||||
}
|
||||
|
||||
inline void AddGhoul2Decal(int shader, vec3_t start, vec3_t dir, float size)
|
||||
{
|
||||
TCGG2Mark *td = (TCGG2Mark *)cl->mSharedMemory;
|
||||
|
||||
td->size = size;
|
||||
td->shader = shader;
|
||||
VectorCopy(start, td->start);
|
||||
VectorCopy(dir, td->dir);
|
||||
|
||||
VM_Call(cgvm, CG_G2MARK);
|
||||
}
|
||||
|
||||
inline void AddFxToScene( refEntity_t *ent )
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
mMainRefs++;
|
||||
|
||||
assert(!ent || ent->renderfx >= 0);
|
||||
#endif
|
||||
re.AddRefEntityToScene( ent );
|
||||
}
|
||||
inline void AddFxToScene( miniRefEntity_t *ent )
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
mMiniRefs++;
|
||||
|
||||
assert(!ent || ent->renderfx >= 0);
|
||||
#endif
|
||||
re.AddMiniRefEntityToScene( ent );
|
||||
}
|
||||
|
||||
inline void AddLightToScene( vec3_t org, float radius, float red, float green, float blue )
|
||||
{
|
||||
re.AddLightToScene( org, radius, red, green, blue );
|
||||
}
|
||||
|
||||
|
||||
inline int RegisterShader( const char *shader )
|
||||
{
|
||||
return re.RegisterShader( shader );
|
||||
}
|
||||
inline int RegisterModel( const char *model )
|
||||
{
|
||||
return re.RegisterModel( model );
|
||||
}
|
||||
|
||||
inline void AddPolyToScene( int shader, int count, polyVert_t *verts )
|
||||
{
|
||||
re.AddPolyToScene( shader, count, verts, 1 );
|
||||
}
|
||||
|
||||
inline void AddDecalToScene ( qhandle_t shader, const vec3_t origin, const vec3_t dir, float orientation, float r, float g, float b, float a, qboolean alphaFade, float radius, qboolean temporary )
|
||||
{
|
||||
re.AddDecalToScene ( shader, origin, dir, orientation, r, g, b, a, alphaFade, radius, temporary );
|
||||
}
|
||||
|
||||
void CameraShake( vec3_t origin, float intensity, int radius, int time );
|
||||
qboolean SFxHelper::GetOriginAxisFromBolt(CGhoul2Info_v *pGhoul2, int mEntNum, int modelNum, int boltNum, vec3_t /*out*/origin, vec3_t /*out*/axis[3]);
|
||||
};
|
||||
|
||||
extern SFxHelper theFxHelper;
|
||||
|
||||
#endif // FX_SYSTEM_H_INC
|
||||
2386
codemp/client/fxtemplate.cpp
Normal file
2386
codemp/client/fxtemplate.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1247
codemp/client/fxutil.cpp
Normal file
1247
codemp/client/fxutil.cpp
Normal file
File diff suppressed because it is too large
Load Diff
116
codemp/client/fxutil.h
Normal file
116
codemp/client/fxutil.h
Normal file
@@ -0,0 +1,116 @@
|
||||
|
||||
#if !defined(FX_PRIMITIVES_H_INC)
|
||||
#include "FxPrimitives.h"
|
||||
#endif
|
||||
|
||||
#ifndef FX_UTIL_H_INC
|
||||
#define FX_UTIL_H_INC
|
||||
|
||||
|
||||
bool FX_Free( bool templates ); // ditches all active effects;
|
||||
int FX_Init( refdef_t* refdef ); // called in CG_Init to purge the fx system.
|
||||
void FX_SetRefDef(refdef_t *refdef);
|
||||
void FX_Add( bool portal ); // called every cgame frame to add all fx into the scene.
|
||||
void FX_Stop( void ); // ditches all active effects without touching the templates.
|
||||
|
||||
|
||||
CParticle *FX_AddParticle( vec3_t org, vec3_t vel, vec3_t accel,
|
||||
float size1, float size2, float sizeParm,
|
||||
float alpha1, float alpha2, float alphaParm,
|
||||
vec3_t rgb1, vec3_t rgb2, float rgbParm,
|
||||
float rotation, float rotationDelta,
|
||||
vec3_t min, vec3_t max, float elasticity,
|
||||
int deathID, int impactID,
|
||||
int killTime, qhandle_t shader, int flags,
|
||||
EMatImpactEffect matImpactFX = MATIMPACTFX_NONE, int fxParm = -1,
|
||||
int iGhoul2=0, int entNum=-1, int modelNum=-1, int boltNum=-1);
|
||||
|
||||
CLine *FX_AddLine( vec3_t start, vec3_t end,
|
||||
float size1, float size2, float sizeParm,
|
||||
float alpha1, float alpha2, float alphaParm,
|
||||
vec3_t rgb1, vec3_t rgb2, float rgbParm,
|
||||
int killTime, qhandle_t shader, int flags,
|
||||
EMatImpactEffect matImpactFX = MATIMPACTFX_NONE, int fxParm = -1,
|
||||
int iGhoul2=0, int entNum=-1, int modelNum=-1, int boltNum=-1);
|
||||
|
||||
CElectricity *FX_AddElectricity( vec3_t start, vec3_t end, float size1, float size2, float sizeParm,
|
||||
float alpha1, float alpha2, float alphaParm,
|
||||
vec3_t sRGB, vec3_t eRGB, float rgbParm,
|
||||
float chaos, int killTime, qhandle_t shader, int flags,
|
||||
EMatImpactEffect matImpactFX = MATIMPACTFX_NONE, int fxParm = -1,
|
||||
int iGhoul2=0, int entNum=-1, int modelNum=-1, int boltNum=-1);
|
||||
|
||||
CTail *FX_AddTail( vec3_t org, vec3_t vel, vec3_t accel,
|
||||
float size1, float size2, float sizeParm,
|
||||
float length1, float length2, float lengthParm,
|
||||
float alpha1, float alpha2, float alphaParm,
|
||||
vec3_t rgb1, vec3_t rgb2, float rgbParm,
|
||||
vec3_t min, vec3_t max, float elasticity,
|
||||
int deathID, int impactID,
|
||||
int killTime, qhandle_t shader, int flags,
|
||||
EMatImpactEffect matImpactFX = MATIMPACTFX_NONE, int fxParm = -1,
|
||||
int iGhoul2=0, int entNum=-1, int modelNum=-1, int boltNum=-1);
|
||||
|
||||
CCylinder *FX_AddCylinder( vec3_t start, vec3_t normal,
|
||||
float size1s, float size1e, float size1Parm,
|
||||
float size2s, float size2e, float size2Parm,
|
||||
float length1, float length2, float lengthParm,
|
||||
float alpha1, float alpha2, float alphaParm,
|
||||
vec3_t rgb1, vec3_t rgb2, float rgbParm,
|
||||
int killTime, qhandle_t shader, int flags,
|
||||
EMatImpactEffect matImpactFX = MATIMPACTFX_NONE, int fxParm = -1,
|
||||
int iGhoul2=0, int entNum=-1, int modelNum=-1, int boltNum=-1,
|
||||
qboolean traceEnd = qfalse);
|
||||
|
||||
CEmitter *FX_AddEmitter( vec3_t org, vec3_t vel, vec3_t accel,
|
||||
float size1, float size2, float sizeParm,
|
||||
float alpha1, float alpha2, float alphaParm,
|
||||
vec3_t rgb1, vec3_t rgb2, float rgbParm,
|
||||
vec3_t angs, vec3_t deltaAngs,
|
||||
vec3_t min, vec3_t max, float elasticity,
|
||||
int deathID, int impactID, int emitterID,
|
||||
float density, float variance,
|
||||
int killTime, qhandle_t model, int flags,
|
||||
EMatImpactEffect matImpactFX = MATIMPACTFX_NONE, int fxParm = -1,
|
||||
int iGhoul2=0, int entNum=-1, int modelNum=-1, int boltNum=-1);
|
||||
|
||||
CLight *FX_AddLight( vec3_t org, float size1, float size2, float sizeParm,
|
||||
vec3_t rgb1, vec3_t rgb2, float rgbParm,
|
||||
int killTime, int flags,
|
||||
EMatImpactEffect matImpactFX = MATIMPACTFX_NONE, int fxParm = -1,
|
||||
int iGhoul2=0, int entNum=-1, int modelNum=-1, int boltNum=-1);
|
||||
|
||||
COrientedParticle *FX_AddOrientedParticle( vec3_t org, vec3_t norm, vec3_t vel, vec3_t accel,
|
||||
float size1, float size2, float sizeParm,
|
||||
float alpha1, float alpha2, float alphaParm,
|
||||
vec3_t rgb1, vec3_t rgb2, float rgbParm,
|
||||
float rotation, float rotationDelta,
|
||||
vec3_t min, vec3_t max, float bounce,
|
||||
int deathID, int impactID,
|
||||
int killTime, qhandle_t shader, int flags,
|
||||
EMatImpactEffect matImpactFX = MATIMPACTFX_NONE, int fxParm = -1,
|
||||
int iGhoul2=0, int entNum=-1, int modelNum=-1, int boltNum=-1);
|
||||
|
||||
CPoly *FX_AddPoly( vec3_t *verts, vec2_t *st, int numVerts,
|
||||
vec3_t vel, vec3_t accel,
|
||||
float alpha1, float alpha2, float alphaParm,
|
||||
vec3_t rgb1, vec3_t rgb2, float rgbParm,
|
||||
vec3_t rotationDelta, float bounce, int motionDelay,
|
||||
int killTime, qhandle_t shader, int flags );
|
||||
|
||||
CFlash *FX_AddFlash( vec3_t origin,
|
||||
float size1, float size2, float sizeParm,
|
||||
float alpha1, float alpha2, float alphaParm,
|
||||
vec3_t sRGB, vec3_t eRGB, float rgbParm,
|
||||
int killTime, qhandle_t shader, int flags = 0,
|
||||
EMatImpactEffect matImpactFX = MATIMPACTFX_NONE, int fxParm = -1);
|
||||
|
||||
CBezier *FX_AddBezier( vec3_t start, vec3_t end,
|
||||
vec3_t control1, vec3_t control1Vel,
|
||||
vec3_t control2, vec3_t control2Vel,
|
||||
float size1, float size2, float sizeParm,
|
||||
float alpha1, float alpha2, float alphaParm,
|
||||
vec3_t sRGB, vec3_t eRGB, float rgbParm,
|
||||
int killTime, qhandle_t shader, int flags = 0 );
|
||||
|
||||
#endif //FX_UTIL_H_INC
|
||||
347
codemp/client/keycodes.h
Normal file
347
codemp/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
|
||||
64
codemp/client/keys.h
Normal file
64
codemp/client/keys.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "../ui/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_CharEvent( field_t *edit, int ch );
|
||||
|
||||
extern field_t chatField;
|
||||
extern qboolean chat_team;
|
||||
extern int chat_playerNum;
|
||||
|
||||
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 );
|
||||
int Key_GetKey(const char *binding);
|
||||
564
codemp/client/openal/al.h
Normal file
564
codemp/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
codemp/client/openal/alc.h
Normal file
97
codemp/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
codemp/client/openal/alctypes.h
Normal file
133
codemp/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
codemp/client/openal/altypes.h
Normal file
351
codemp/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
codemp/client/openal/alu.h
Normal file
34
codemp/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
codemp/client/openal/alut.h
Normal file
24
codemp/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
|
||||
1137
codemp/client/snd_ambient.cpp
Normal file
1137
codemp/client/snd_ambient.cpp
Normal file
File diff suppressed because it is too large
Load Diff
118
codemp/client/snd_ambient.h
Normal file
118
codemp/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 listener_origin, vec3_t origin, int entID, int time );
|
||||
|
||||
extern sfxHandle_t AS_GetBModelSound( const char *name, int stage );
|
||||
|
||||
#endif //__SND_AMBIENT__
|
||||
6332
codemp/client/snd_dma.cpp
Normal file
6332
codemp/client/snd_dma.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2990
codemp/client/snd_dma_console.cpp
Normal file
2990
codemp/client/snd_dma_console.cpp
Normal file
File diff suppressed because it is too large
Load Diff
228
codemp/client/snd_local.h
Normal file
228
codemp/client/snd_local.h
Normal file
@@ -0,0 +1,228 @@
|
||||
// snd_local.h -- private sound definations
|
||||
|
||||
#ifndef SND_LOCAL_H
|
||||
#define SND_LOCAL_H
|
||||
|
||||
#define sboolean int //rww - argh (in SP qboolean type is merely #define'd as an int, but I do not want to do that for MP over the whole base)
|
||||
|
||||
#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(sboolean 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;
|
||||
sboolean bDefaultSound; // couldn't be loaded, so use buzz
|
||||
sboolean bInMemory; // not in Memory, set qtrue when loaded, and qfalse when its buffers are freed up because of being old, so can be reloaded
|
||||
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
|
||||
int iLastLevelUsedOn; // used for cacheing purposes
|
||||
|
||||
// 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: sboolean loopSound; // from an S_AddLoopSound call, cleared each frame
|
||||
//
|
||||
unsigned int startSample; // START_SAMPLE_IMMEDIATE = set immediately on next mix
|
||||
int entnum; // to allow overriding a specific sound
|
||||
int 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
|
||||
|
||||
sboolean fixed_origin; // use origin instead of fetching entnum's origin
|
||||
sfx_t *thesfx; // sfx structure
|
||||
sboolean 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);
|
||||
|
||||
sboolean 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 "snd_mp3.h"
|
||||
|
||||
#endif // #ifndef SND_LOCAL_H
|
||||
|
||||
134
codemp/client/snd_local_console.h
Normal file
134
codemp/client/snd_local_console.h
Normal file
@@ -0,0 +1,134 @@
|
||||
// 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;
|
||||
} 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
|
||||
ALuint Buffer;
|
||||
} 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[MAX_GENTITIES];
|
||||
|
||||
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);
|
||||
|
||||
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
codemp/client/snd_mem.cpp
Normal file
1015
codemp/client/snd_mem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
353
codemp/client/snd_mem_console.cpp
Normal file
353
codemp/client/snd_mem_console.cpp
Normal file
@@ -0,0 +1,353 @@
|
||||
// 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];
|
||||
|
||||
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 code);
|
||||
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];
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
470
codemp/client/snd_mix.cpp
Normal file
470
codemp/client/snd_mix.cpp
Normal file
@@ -0,0 +1,470 @@
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
// snd_mix.c -- portable code to mix sounds for snd_dma.c
|
||||
|
||||
// leave this as first line for PCH reasons...
|
||||
//
|
||||
#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;
|
||||
voice_vol = (int)(s_volumeVoice->value*256);
|
||||
|
||||
//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;
|
||||
}
|
||||
}
|
||||
553
codemp/client/snd_mp3.cpp
Normal file
553
codemp/client/snd_mp3.cpp
Normal file
@@ -0,0 +1,553 @@
|
||||
//Anything above this #include will be ignored by the compiler
|
||||
#include "../qcommon/exe_headers.h"
|
||||
|
||||
// Filename:- cl_mp3.cpp
|
||||
//
|
||||
// (The interface module between all the MP3 stuff and the game)
|
||||
|
||||
|
||||
#include "client.h"
|
||||
#include "snd_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
|
||||
//
|
||||
sboolean MP3_IsValid( const char *psLocalFilename, void *pvData, int iDataLen, sboolean 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, sboolean qbIgnoreID3Tag /* = qfalse */
|
||||
, sboolean 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, sboolean 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)...
|
||||
//
|
||||
sboolean MP3Stream_InitPlayingTimeFields( LP_MP3STREAM lpMP3Stream, const char *psLocalFilename, void *pvData, int iDataLen, sboolean bStereoDesired /* = qfalse */)
|
||||
{
|
||||
sboolean 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, // sboolean 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
|
||||
//
|
||||
sboolean MP3_FakeUpWAVInfo( const char *psLocalFilename, void *pvData, int iDataLen, int iUnpackedDataLength,
|
||||
int &format, int &rate, int &width, int &channels, int &samples, int &dataofs,
|
||||
sboolean 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...
|
||||
//
|
||||
sboolean MP3_ReadSpecialTagInfo(byte *pbLoadedFile, int iLoadedFileLen,
|
||||
id3v1_1** ppTAG /* = NULL */,
|
||||
int *piUncompressedSize /* = NULL */,
|
||||
float *pfMaxVol /* = NULL */
|
||||
)
|
||||
{
|
||||
sboolean 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)
|
||||
//
|
||||
sboolean MP3Stream_InitFromFile( sfx_t* sfx, byte *pbSrcData, int iSrcDatalen, const char *psSrcDataFilename,
|
||||
int iMP3UnPackedSize, sboolean 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, sboolean 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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sboolean 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
|
||||
//
|
||||
sboolean 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
|
||||
//
|
||||
sboolean MP3Stream_GetSamples( channel_t *ch, int startingSampleNum, int count, short *buf, sboolean bStereo )
|
||||
{
|
||||
sboolean 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));
|
||||
|
||||
// sboolean _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
codemp/client/snd_mp3.h
Normal file
87
codemp/client/snd_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 );
|
||||
sboolean MP3_IsValid ( const char *psLocalFilename, void *pvData, int iDataLen, sboolean bStereoDesired = qfalse );
|
||||
int MP3_GetUnpackedSize ( const char *psLocalFilename, void *pvData, int iDataLen, sboolean qbIgnoreID3Tag = qfalse, sboolean bStereoDesired = qfalse );
|
||||
sboolean MP3_UnpackRawPCM ( const char *psLocalFilename, void *pvData, int iDataLen, byte *pbUnpackBuffer, sboolean bStereoDesired = qfalse );
|
||||
sboolean MP3Stream_InitPlayingTimeFields( LP_MP3STREAM lpMP3Stream, const char *psLocalFilename, void *pvData, int iDataLen, sboolean bStereoDesired = qfalse);
|
||||
float MP3Stream_GetPlayingTimeInSeconds( LP_MP3STREAM lpMP3Stream );
|
||||
float MP3Stream_GetRemainingTimeInSeconds( LP_MP3STREAM lpMP3Stream );
|
||||
sboolean MP3_FakeUpWAVInfo ( const char *psLocalFilename, void *pvData, int iDataLen, int iUnpackedDataLength, int &format, int &rate, int &width, int &channels, int &samples, int &dataofs, sboolean bStereoDesired = qfalse );
|
||||
sboolean MP3_ReadSpecialTagInfo ( byte *pbLoadedFile, int iLoadedFileLen,
|
||||
id3v1_1** ppTAG = NULL, int *piUncompressedSize = NULL, float *pfMaxVol = NULL);
|
||||
sboolean MP3Stream_InitFromFile ( sfx_t* sfx, byte *pbSrcData, int iSrcDatalen, const char *psSrcDataFilename, int iMP3UnPackedSize, sboolean bStereoDesired = qfalse );
|
||||
int MP3Stream_Decode ( LP_MP3STREAM lpMP3Stream, sboolean bDoingMusic );
|
||||
sboolean MP3Stream_SeekTo ( channel_t *ch, float fTimeToSeekTo );
|
||||
sboolean MP3Stream_Rewind ( channel_t *ch );
|
||||
sboolean MP3Stream_GetSamples ( channel_t *ch, int startingSampleNum, int count, short *buf, sboolean 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 /////////////////////
|
||||
|
||||
1153
codemp/client/snd_music.cpp
Normal file
1153
codemp/client/snd_music.cpp
Normal file
File diff suppressed because it is too large
Load Diff
65
codemp/client/snd_music.h
Normal file
65
codemp/client/snd_music.h
Normal file
@@ -0,0 +1,65 @@
|
||||
// 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 );
|
||||
sboolean Music_DynamicDataAvailable ( const char *psDynamicMusicLabel );
|
||||
const char *Music_GetFileNameForState ( MusicState_e eMusicState );
|
||||
sboolean Music_StateIsTransition ( MusicState_e eMusicState );
|
||||
sboolean Music_StateCanBeInterrupted ( MusicState_e eMusicState, MusicState_e eProposedMusicState );
|
||||
float Music_GetRandomEntryTime ( MusicState_e eMusicState );
|
||||
|
||||
sboolean Music_AllowedToTransition ( float fPlayingTimeElapsed, MusicState_e eMusicState, MusicState_e *peTransition = NULL, float *pfNewTrackEntryTime = NULL);
|
||||
|
||||
const char *Music_BaseStateToString ( MusicState_e eMusicState, sboolean bDebugPrintQuery = qfalse);
|
||||
|
||||
|
||||
#endif // #ifndef SND_MUSIC_H
|
||||
|
||||
|
||||
//////////////// eof /////////////////
|
||||
|
||||
|
||||
67
codemp/client/snd_public.h
Normal file
67
codemp/client/snd_public.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef _SND_PUBLIC_H
|
||||
#define _SND_PUBLIC_H
|
||||
|
||||
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_MuteSound(int entityNum, int entchannel);
|
||||
void S_StartSound( const vec3_t origin, int entnum, int 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, int 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, int 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_StopLoopingSound( int entityNum );
|
||||
#ifdef _XBOX
|
||||
void S_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx, int chan = 0 );
|
||||
#else
|
||||
void S_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
|
||||
#endif
|
||||
|
||||
// recompute the reletive volumes for all running sounds
|
||||
// relative to the given entityNum / orientation
|
||||
void S_Respatialize( int entityNum, const vec3_t head, vec3_t axis[3], int 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 );
|
||||
|
||||
#ifdef _XBOX
|
||||
void S_BeginRegistration( int num_listeners );
|
||||
#else
|
||||
void S_BeginRegistration( void );
|
||||
#endif
|
||||
|
||||
// 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 );
|
||||
|
||||
extern qboolean s_shutUp;
|
||||
|
||||
void S_FreeAllSFXMem(void);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user