Initial commit.

This commit is contained in:
Jim Gray
2013-04-04 14:32:05 -07:00
parent ba5c81da32
commit d71d53e8ec
2180 changed files with 1393544 additions and 1 deletions

412
codemp/client/0_sh_leak.cpp Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

1499
codemp/client/cl_cin.cpp Normal file

File diff suppressed because it is too large Load Diff

View 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;
}

View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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();
}

View 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

File diff suppressed because it is too large Load Diff

2337
codemp/client/cl_main.cpp Normal file

File diff suppressed because it is too large Load Diff

View 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

File diff suppressed because it is too large Load Diff

486
codemp/client/cl_scrn.cpp Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

171
codemp/client/eax/eaxman.h Normal file
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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

File diff suppressed because it is too large Load Diff

505
codemp/client/fxscheduler.h Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

1247
codemp/client/fxutil.cpp Normal file

File diff suppressed because it is too large Load Diff

116
codemp/client/fxutil.h Normal file
View 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
View 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
View 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
View 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

View 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

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

118
codemp/client/snd_ambient.h Normal file
View 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

228
codemp/client/snd_local.h Normal file
View 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

View 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

File diff suppressed because it is too large Load Diff

View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

65
codemp/client/snd_music.h Normal file
View 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 /////////////////

View 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