reworked demo playback and interpolation.

added support for recording nq demos, but only if not already on the server.
added capturedriver as a sane way to select between screenshots, avi, or various plugins.
output sound device can now be selected via the menu. not all drivers provide device enumeration (openal and dsound do).
enabled openal, but not using it unless an openal device is explicitly requested as its still a little buggy.
added \"\"" markup in the console.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4427 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2013-07-26 17:19:06 +00:00
parent 7d4c88814e
commit fceb09fe37
47 changed files with 2379 additions and 1333 deletions

View File

@ -518,9 +518,16 @@ MP3_OBJS = \
huffman.o \
mymad.o
PROGS_OBJS = \
QCC_OBJS= \
comprout.o \
hash.o \
qcc_cmdlib.o \
qccmain.o \
qcc_pr_comp.o \
qcc_pr_lex.o \
qcd_main.o
PROGS_OBJS = \
$(QCC_OBJS) \
initlib.o \
pr_bgcmd.o \
pr_skelobj.o \
@ -528,12 +535,7 @@ PROGS_OBJS = \
pr_exec.o \
pr_multi.o \
pr_x86.o \
qcc_cmdlib.o \
qccmain.o \
qcc_pr_comp.o \
qcc_pr_lex.o \
qcdecomp.o \
qcd_main.o
qcdecomp.o
SERVER_OBJS = \
pr_cmds.o \
@ -1372,6 +1374,17 @@ m-profile:
.PHONY: m-tmp mcl-tmp mingl-tmp glcl-tmp gl-tmp sv-tmp _clsv-dbg _clsv-rel _cl-dbg _cl-rel _out-rel _out-dbg
_qcc-tmp: $(REQDIR)
@$(MAKE) $(TYPE) EXE_NAME="$(EXE_NAME)" PRECOMPHEADERS="" OUT_DIR="$(OUT_DIR)" WCFLAGS="$(CLIENT_ONLY_CFLAGS) $(WCFLAGS)" LDFLAGS="$(LDFLAGS)" OBJS="QCC_OBJS SOBJS"
qcc-rel:
@$(MAKE) _qcc-tmp TYPE=_out-rel REQDIR=reldir EXE_NAME="../fteqcc" OUT_DIR="$(RELEASE_DIR)/qcc" SOBJS="qcctui.o"
qccgui-rel:
@$(MAKE) _qcc-tmp TYPE=_out-rel REQDIR=reldir EXE_NAME="../fteqccgui" OUT_DIR="$(RELEASE_DIR)/qcc" SOBJS="qccgui.o qccguistuff.o" LDFLAGS="$(LDFLAGS) -lcomdlg32 -lcomctl32"
qcc-dbg:
@$(MAKE) _qcc-tmp TYPE=_out-dbg REQDIR=debugdir EXE_NAME="../fteqcc" OUT_DIR="$(RELEASE_DIR)/qcc" SOBJS="qcctui.o"
qccgui-dbg:
@$(MAKE) _qcc-tmp TYPE=_out-dbg REQDIR=debugdir EXE_NAME="../fteqccgui" OUT_DIR="$(RELEASE_DIR)/qcc" SOBJS="qccgui.o qccguistuff.o" LDFLAGS="$(LDFLAGS) -lcomdlg32 -lcomctl32"
ifdef windir
debugdir:
@-mkdir -p $(subst /,\, $(OUT_DIR))

View File

@ -868,7 +868,7 @@ static void Init_AI_Export( ai_export_t *ai ) {
GetBotLibAPI
============
*/
botlib_export_t *GetBotLibAPI(int apiVersion, botlib_import_t *import) {
botlib_export_t *QDECL GetBotLibAPI(int apiVersion, botlib_import_t *import) {
assert(import);
botimport = *import;
assert(botimport.Print);

View File

@ -431,7 +431,7 @@ typedef struct botlib_export_s
} botlib_export_t;
//linking of bot library
botlib_export_t *GetBotLibAPI( int apiVersion, botlib_import_t *import );
botlib_export_t *QDECL GetBotLibAPI( int apiVersion, botlib_import_t *import );
/* Library variables:

View File

@ -92,6 +92,10 @@ void CL_WriteDemoCmd (usercmd_t *pcmd)
qbyte c;
q1usercmd_t cmd;
//nq doesn't have this info
if (cls.demorecording != 1)
return;
//Con_Printf("write: %ld bytes, %4.4f\n", msg->cursize, demtime);
fl = LittleFloat((float)demtime);
@ -131,7 +135,7 @@ CL_WriteDemoMessage
Dumps the current net message, prefixed by the length and view angles
====================
*/
void CL_WriteDemoMessage (sizebuf_t *msg)
void CL_WriteDemoMessage (sizebuf_t *msg, int payloadoffset)
{
int len;
int i;
@ -140,37 +144,50 @@ void CL_WriteDemoMessage (sizebuf_t *msg)
//Con_Printf("write: %ld bytes, %4.4f\n", msg->cursize, demtime);
if (!cls.demorecording)
switch (cls.demorecording)
{
case 0:
return;
case 1: //QW
fl = LittleFloat((float)demtime);
VFS_WRITE (cls.demooutfile, &fl, sizeof(fl));
fl = LittleFloat((float)demtime);
VFS_WRITE (cls.demooutfile, &fl, sizeof(fl));
c = dem_read;
VFS_WRITE (cls.demooutfile, &c, sizeof(c));
c = dem_read;
VFS_WRITE (cls.demooutfile, &c, sizeof(c));
if (*(int*)msg->data == -1)
{
//connectionless packet.
len = LittleLong (msg->cursize);
VFS_WRITE (cls.demooutfile, &len, 4);
VFS_WRITE (cls.demooutfile, msg->data + msg_readcount, msg->cursize - msg_readcount);
if (*(int*)msg->data == -1)
{
//connectionless packet.
len = LittleLong (msg->cursize);
VFS_WRITE (cls.demooutfile, &len, 4);
VFS_WRITE (cls.demooutfile, msg->data + msg_readcount, msg->cursize - msg_readcount);
}
else
{
//regenerate a legacy netchan. no fragmentation support, but whatever. this ain't udp.
//the length
len = LittleLong (msg->cursize - msg_readcount + 8);
VFS_WRITE (cls.demooutfile, &len, 4);
//hack the netchan here.
i = cls.netchan.incoming_sequence;
VFS_WRITE (cls.demooutfile, &i, 4);
i = cls.netchan.incoming_acknowledged;
VFS_WRITE (cls.demooutfile, &i, 4);
//and the data
VFS_WRITE (cls.demooutfile, msg->data + msg_readcount, msg->cursize - msg_readcount);
}
break;
case 2: //NQ
len = LittleLong (net_message.cursize - payloadoffset);
VFS_WRITE(cls.demooutfile, &len, sizeof(len));
for (i=0 ; i<3 ; i++)
{
float f = LittleFloat (cl.playerview[0].viewangles[i]);
VFS_WRITE(cls.demooutfile, &f, sizeof(f));
}
VFS_WRITE(cls.demooutfile, net_message.data + payloadoffset, net_message.cursize - payloadoffset);
break;
}
else
{
//regenerate a legacy netchan. no fragmentation support, but whatever. this ain't udp.
//the length
len = LittleLong (msg->cursize - msg_readcount + 8);
VFS_WRITE (cls.demooutfile, &len, 4);
//hack the netchan here.
i = cls.netchan.incoming_sequence;
VFS_WRITE (cls.demooutfile, &i, 4);
i = cls.netchan.incoming_acknowledged;
VFS_WRITE (cls.demooutfile, &i, 4);
//and the data
VFS_WRITE (cls.demooutfile, msg->data + msg_readcount, msg->cursize - msg_readcount);
}
VFS_FLUSH (cls.demooutfile);
}
@ -244,6 +261,8 @@ int readdemobytes(int *readpos, void *data, int len)
{
int i;
int trybytes;
if (len < 0)
Host_EndGame("Corrupt demo");
if (demopreparsedbytes < 0) //won't happen in normal running, but can still happen on corrupt data... if we don't disconnect first.
{
@ -391,6 +410,7 @@ CL_GetDemoMessage
====================
*/
vec3_t demoangles;
float olddemotime = 0;
float nextdemotime = 0;
qboolean CL_GetDemoMessage (void)
@ -456,27 +476,7 @@ qboolean CL_GetDemoMessage (void)
if ((cls.timedemo && host_framecount == demoframe) || (!cls.timedemo && demtime<= cl.gametime && cl.gametime))// > dem_lasttime+demtime)
{
if (demtime <= cl.gametime-1)
{
demtime = cl.gametime;
}
{
float f = (cl.gametime-demtime)/(cl.gametime-olddemotime);
float a1;
float a2;
for (i=0 ; i<3 ; i++)
{
a1 = cl.playerview[2].viewangles[i];
a2 = cl.playerview[1].viewangles[i];
if (a1 - a2 > 180)
a1 -= 360;
if (a1 - a2 < -180)
a1 += 360;
cl.playerview[0].simangles[i] = a2 + f * (a1 - a2);
}
VectorCopy(cl.playerview[0].simangles, cl.playerview[0].viewangles);
}
return 0;
}
demoframe = host_framecount;
@ -487,13 +487,11 @@ qboolean CL_GetDemoMessage (void)
}
if (cls.demoplayback == DPB_NETQUAKE)
{
VectorCopy (cl.playerview[1].viewangles, cl.playerview[2].viewangles);
for (i=0 ; i<3 ; i++)
{
readdemobytes(&demopos, &f, 4);
cl.playerview[0].simangles[i] = cl.playerview[1].viewangles[i] = LittleFloat (f);
demoangles[i] = LittleFloat (f);
}
VectorCopy (cl.playerview[1].viewangles, cl.playerview[0].viewangles);
}
olddemotime = demtime;
@ -645,42 +643,6 @@ readnext:
Con_Printf("mvd demos/qtv streams should not contain dem_cmd\n");
olddemotime = demtime+1;
CL_StopPlayback ();
/*
unsigned short samps;
unsigned char bits;
unsigned char rateid;
unsigned char audio[8192];
if (readdemobytes (&demopos, &samps, 2) == 2)
{
if (readdemobytes (&demopos, &bits, 1) == 1)
{
if (samps > sizeof(audio))
{
Con_Printf("Corrupted/too large audio chunk\n");
CL_StopPlayback();
return 0;
}
if (readdemobytes (&demopos, &rateid, 1) == 1)
{
if (readdemobytes (&demopos, audio, samps) == samps)
{
FILE *f;
samps = samps/(bits/8);
f = fopen("c:/test.raw", "r+b");
if (f)
{
fseek(f, 0, SEEK_END);
fwrite(audio, samps, bits/8, f);
fclose(f);
}
S_RawAudio(0, audio, 11025, samps, 1, bits/8);
break;
}
}
}
}
*/
return 0;
}
else
@ -715,6 +677,7 @@ readnext:
for (i=0 ; i<3 ; i++)
{
readdemobytes (&demopos, &f, 4);
demoangles[i] = LittleFloat (f);
cl.playerview[0].viewangles[i] = LittleFloat (f);
}
goto readnext;
@ -880,8 +843,9 @@ void CL_Stop_f (void)
{
#ifndef CLIENTONLY
SV_MVDStop_f();
#endif
#else
Con_Printf ("Not recording a demo.\n");
#endif
return;
}
@ -890,7 +854,7 @@ void CL_Stop_f (void)
MSG_WriteLong (&net_message, -1); // -1 sequence means out of band
MSG_WriteByte (&net_message, svc_disconnect);
MSG_WriteString (&net_message, "EndOfDemo");
CL_WriteDemoMessage (&net_message);
CL_WriteDemoMessage (&net_message, sizeof(int));
// finish up
VFS_CLOSE (cls.demooutfile);
@ -946,7 +910,7 @@ void CL_WriteSetDemoMessage (void)
//Con_Printf("write: %ld bytes, %4.4f\n", msg->cursize, demtime);
if (!cls.demorecording)
if (cls.demorecording != 1)
return;
fl = LittleFloat((float)demtime);
@ -964,7 +928,52 @@ void CL_WriteSetDemoMessage (void)
}
/*
record a single player game.
*/
#ifndef CLIENTONLY
mvddest_t *SV_InitRecordFile (char *name);
qboolean SV_MVD_Record (mvddest_t *dest);
void CL_RecordMap_f (void)
{
char demoname[MAX_QPATH];
char mapname[MAX_QPATH];
char *demoext;
Q_strncpyz(demoname, Cmd_Argv(1), sizeof(demoname));
Q_strncpyz(mapname, Cmd_Argv(2), sizeof(mapname));
CL_Disconnect_f();
SV_SpawnServer (mapname, NULL, false, false);
COM_DefaultExtension(demoname, ".mvd", sizeof(demoname));
demoext = COM_FileExtension(demoname);
if (!strcmp(demoext, "mvd"))
{
if (!SV_MVD_Record (SV_InitRecordFile(demoname)))
CL_Disconnect_f();
// char buf[512];
// Cbuf_AddText(va("mvdrecord %s\n", COM_QuotedString(demoname, buf, sizeof(buf))), RESTRICT_LOCAL);
}
else
{
cls.demooutfile = FS_OpenVFS (demoname, "wb", FS_GAME);
if (!cls.demooutfile)
{
CL_Disconnect_f();
return;
}
if (!strcmp(demoext, "dem"))
{
cls.demorecording = 2;
VFS_PUTS(cls.demooutfile, "-1\n");
}
else
cls.demorecording = 1;
CL_WriteSetDemoMessage();
}
}
#endif
/*
====================
@ -990,6 +999,9 @@ void CL_Record_f (void)
c = Cmd_Argc();
if (c > 2)
{
#ifndef CLIENTONLY
CL_RecordMap_f();
#endif
Con_Printf ("record <demoname>\n");
return;
}
@ -1110,199 +1122,172 @@ void CL_Record_f (void)
/*-------------------------------------------------*/
// serverdata
// send the info about the new client to all connected clients
memset(&buf, 0, sizeof(buf));
buf.data = buf_data;
buf.maxsize = sizeof(buf_data);
buf.prim = cls.netchan.netprim;
switch(cls.protocol)
{
case CP_QUAKEWORLD:
// send the serverdata
MSG_WriteByte (&buf, svc_serverdata);
// serverdata
// send the info about the new client to all connected clients
memset(&buf, 0, sizeof(buf));
buf.data = buf_data;
buf.maxsize = sizeof(buf_data);
buf.prim = cls.netchan.netprim;
// send the serverdata
MSG_WriteByte (&buf, svc_serverdata);
#ifdef PROTOCOL_VERSION_FTE
if (cls.fteprotocolextensions) //maintain demo compatability
{
MSG_WriteLong (&buf, PROTOCOL_VERSION_FTE);
MSG_WriteLong (&buf, cls.fteprotocolextensions);
}
if (cls.fteprotocolextensions2) //maintain demo compatability
{
MSG_WriteLong (&buf, PROTOCOL_VERSION_FTE2);
MSG_WriteLong (&buf, cls.fteprotocolextensions2);
}
if (cls.fteprotocolextensions) //maintain demo compatability
{
MSG_WriteLong (&buf, PROTOCOL_VERSION_FTE);
MSG_WriteLong (&buf, cls.fteprotocolextensions);
}
if (cls.fteprotocolextensions2) //maintain demo compatability
{
MSG_WriteLong (&buf, PROTOCOL_VERSION_FTE2);
MSG_WriteLong (&buf, cls.fteprotocolextensions2);
}
#endif
MSG_WriteLong (&buf, PROTOCOL_VERSION_QW);
MSG_WriteLong (&buf, cl.servercount);
MSG_WriteString (&buf, gamedirfile);
MSG_WriteLong (&buf, PROTOCOL_VERSION_QW);
MSG_WriteLong (&buf, cl.servercount);
MSG_WriteString (&buf, gamedirfile);
if (cls.fteprotocolextensions2 & PEXT2_MAXPLAYERS)
{
MSG_WriteByte (&buf, cl.allocated_client_slots);
MSG_WriteByte (&buf, cl.splitclients | (cl.spectator?128:0));
for (i = 0; i < cl.splitclients; i++)
if (cls.fteprotocolextensions2 & PEXT2_MAXPLAYERS)
{
MSG_WriteByte (&buf, cl.playerview[i].playernum);
}
}
else
{
for (i = 0; i < cl.splitclients; i++)
{
if (cl.spectator)
MSG_WriteByte (&buf, cl.playerview[i].playernum | 128);
else
MSG_WriteByte (&buf, cl.allocated_client_slots);
MSG_WriteByte (&buf, cl.splitclients | (cl.spectator?128:0));
for (i = 0; i < cl.splitclients; i++)
{
MSG_WriteByte (&buf, cl.playerview[i].playernum);
}
}
else
{
for (i = 0; i < cl.splitclients; i++)
{
if (cl.spectator)
MSG_WriteByte (&buf, cl.playerview[i].playernum | 128);
else
MSG_WriteByte (&buf, cl.playerview[i].playernum);
}
if (cls.fteprotocolextensions & PEXT_SPLITSCREEN)
MSG_WriteByte (&buf, 128);
}
if (cls.fteprotocolextensions & PEXT_SPLITSCREEN)
MSG_WriteByte (&buf, 128);
}
// send full levelname
MSG_WriteString (&buf, cl.levelname);
// send full levelname
MSG_WriteString (&buf, cl.levelname);
// send the movevars
MSG_WriteFloat(&buf, movevars.gravity);
MSG_WriteFloat(&buf, movevars.stopspeed);
MSG_WriteFloat(&buf, movevars.maxspeed);
MSG_WriteFloat(&buf, movevars.spectatormaxspeed);
MSG_WriteFloat(&buf, movevars.accelerate);
MSG_WriteFloat(&buf, movevars.airaccelerate);
MSG_WriteFloat(&buf, movevars.wateraccelerate);
MSG_WriteFloat(&buf, movevars.friction);
MSG_WriteFloat(&buf, movevars.waterfriction);
MSG_WriteFloat(&buf, movevars.entgravity);
// send the movevars
MSG_WriteFloat(&buf, movevars.gravity);
MSG_WriteFloat(&buf, movevars.stopspeed);
MSG_WriteFloat(&buf, movevars.maxspeed);
MSG_WriteFloat(&buf, movevars.spectatormaxspeed);
MSG_WriteFloat(&buf, movevars.accelerate);
MSG_WriteFloat(&buf, movevars.airaccelerate);
MSG_WriteFloat(&buf, movevars.wateraccelerate);
MSG_WriteFloat(&buf, movevars.friction);
MSG_WriteFloat(&buf, movevars.waterfriction);
MSG_WriteFloat(&buf, movevars.entgravity);
// send server info string
MSG_WriteByte (&buf, svc_stufftext);
MSG_WriteString (&buf, va("fullserverinfo \"%s\"\n", cl.serverinfo) );
// send server info string
MSG_WriteByte (&buf, svc_stufftext);
MSG_WriteString (&buf, va("fullserverinfo \"%s\"\n", cl.serverinfo) );
// send music (delayed)
MSG_WriteByte (&buf, svc_cdtrack);
MSG_WriteByte (&buf, 0); // none in demos
// send music (delayed)
MSG_WriteByte (&buf, svc_cdtrack);
MSG_WriteByte (&buf, 0); // none in demos
#ifdef PEXT_SETVIEW
if (cl.playerview[0].viewentity != cl.playerview[0].playernum+1) //tell the player if we have a different view entity
{
MSG_WriteByte (&buf, svc_setview);
MSG_WriteEntity (&buf, cl.playerview[0].viewentity);
}
if (cl.playerview[0].viewentity != cl.playerview[0].playernum+1) //tell the player if we have a different view entity
{
MSG_WriteByte (&buf, svc_setview);
MSG_WriteEntity (&buf, cl.playerview[0].viewentity);
}
#endif
// flush packet
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
// flush packet
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
// soundlist
MSG_WriteByte (&buf, svc_soundlist);
MSG_WriteByte (&buf, 0);
// soundlist
MSG_WriteByte (&buf, svc_soundlist);
MSG_WriteByte (&buf, 0);
n = 0;
s = cl.sound_name[n+1];
while (*s)
{
MSG_WriteString (&buf, s);
if (buf.cursize > MAX_QWMSGLEN/2)
{
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, n);
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
MSG_WriteByte (&buf, svc_soundlist);
MSG_WriteByte (&buf, n + 1);
}
n++;
n = 0;
s = cl.sound_name[n+1];
}
if (buf.cursize)
{
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0);
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
// modellist
MSG_WriteByte (&buf, svc_modellist);
MSG_WriteByte (&buf, 0);
n = 0;
s = cl.model_name[n+1];
while (*s)
{
MSG_WriteString (&buf, s);
if (buf.cursize > MAX_QWMSGLEN/2)
while (*s)
{
MSG_WriteString (&buf, s);
if (buf.cursize > MAX_QWMSGLEN/2)
{
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, n);
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
MSG_WriteByte (&buf, svc_soundlist);
MSG_WriteByte (&buf, n + 1);
}
n++;
s = cl.sound_name[n+1];
}
if (buf.cursize)
{
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, n);
MSG_WriteByte (&buf, 0);
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
MSG_WriteByte (&buf, svc_modellist);
MSG_WriteByte (&buf, n + 1);
}
n++;
// modellist
MSG_WriteByte (&buf, svc_modellist);
MSG_WriteByte (&buf, 0);
n = 0;
s = cl.model_name[n+1];
}
if (buf.cursize)
{
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0);
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
// spawnstatic
for (i = 0; i < cl.num_statics; i++)
{
ent = &cl_static_entities[i].ent;
MSG_WriteByte (&buf, svc_spawnstatic);
for (j = 1; j < MAX_MODELS; j++)
if (ent->model == cl.model_precache[j])
break;
if (j == MAX_MODELS)
MSG_WriteByte (&buf, 0);
else
MSG_WriteByte (&buf, j);
MSG_WriteByte (&buf, ent->framestate.g[FS_REG].frame[0]);
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, ent->skinnum);
for (j=0 ; j<3 ; j++)
while (*s)
{
MSG_WriteCoord (&buf, ent->origin[j]);
MSG_WriteAngle (&buf, ent->angles[j]);
MSG_WriteString (&buf, s);
if (buf.cursize > MAX_QWMSGLEN/2)
{
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, n);
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
MSG_WriteByte (&buf, svc_modellist);
MSG_WriteByte (&buf, n + 1);
}
n++;
s = cl.model_name[n+1];
}
if (buf.cursize > MAX_QWMSGLEN/2)
if (buf.cursize)
{
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0);
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
}
// spawnstaticsound
// static sounds are skipped in demos, life is hard
// spawnstatic
// baselines
for (i = 0; i < cl_baselines_count; i++)
{
es = cl_baselines + i;
if (memcmp(es, &nullentitystate, sizeof(nullentitystate)))
for (i = 0; i < cl.num_statics; i++)
{
MSG_WriteByte (&buf,svc_spawnbaseline);
MSG_WriteEntity (&buf, i);
ent = &cl_static_entities[i].ent;
MSG_WriteByte (&buf, es->modelindex);
MSG_WriteByte (&buf, es->frame);
MSG_WriteByte (&buf, es->colormap);
MSG_WriteByte (&buf, es->skinnum);
MSG_WriteByte (&buf, svc_spawnstatic);
for (j = 1; j < MAX_MODELS; j++)
if (ent->model == cl.model_precache[j])
break;
if (j == MAX_MODELS)
MSG_WriteByte (&buf, 0);
else
MSG_WriteByte (&buf, j);
MSG_WriteByte (&buf, ent->framestate.g[FS_REG].frame[0]);
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, ent->skinnum);
for (j=0 ; j<3 ; j++)
{
MSG_WriteCoord(&buf, es->origin[j]);
MSG_WriteAngle(&buf, es->angles[j]);
MSG_WriteCoord (&buf, ent->origin[j]);
MSG_WriteAngle (&buf, ent->angles[j]);
}
if (buf.cursize > MAX_QWMSGLEN/2)
@ -1311,114 +1296,151 @@ void CL_Record_f (void)
SZ_Clear (&buf);
}
}
}
MSG_WriteByte (&buf, svc_stufftext);
MSG_WriteString (&buf, va("cmd spawn %i\n", cl.servercount) );
// spawnstaticsound
// static sounds are skipped in demos, life is hard
if (buf.cursize)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
// baselines
// send current status of all other players
for (i = 0; i < cl.allocated_client_slots; i++)
{
player = cl.players + i;
if (player->frags != 0)
for (i = 0; i < cl_baselines_count; i++)
{
MSG_WriteByte (&buf, svc_updatefrags);
MSG_WriteByte (&buf, i);
MSG_WriteShort (&buf, player->frags);
es = cl_baselines + i;
if (memcmp(es, &nullentitystate, sizeof(nullentitystate)))
{
MSG_WriteByte (&buf,svc_spawnbaseline);
MSG_WriteEntity (&buf, i);
MSG_WriteByte (&buf, es->modelindex);
MSG_WriteByte (&buf, es->frame);
MSG_WriteByte (&buf, es->colormap);
MSG_WriteByte (&buf, es->skinnum);
for (j=0 ; j<3 ; j++)
{
MSG_WriteCoord(&buf, es->origin[j]);
MSG_WriteAngle(&buf, es->angles[j]);
}
if (buf.cursize > MAX_QWMSGLEN/2)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
}
}
if (player->ping != 0)
{
MSG_WriteByte (&buf, svc_updateping);
MSG_WriteByte (&buf, i);
MSG_WriteShort (&buf, player->ping);
}
MSG_WriteByte (&buf, svc_stufftext);
MSG_WriteString (&buf, va("cmd spawn %i\n", cl.servercount) );
if (player->pl != 0)
{
MSG_WriteByte (&buf, svc_updatepl);
MSG_WriteByte (&buf, i);
MSG_WriteByte (&buf, player->pl);
}
if (*player->userinfo)
{
MSG_WriteByte (&buf, svc_updateentertime);
MSG_WriteByte (&buf, i);
MSG_WriteFloat (&buf, player->entertime);
}
if (*player->userinfo)
{
MSG_WriteByte (&buf, svc_updateuserinfo);
MSG_WriteByte (&buf, i);
MSG_WriteLong (&buf, player->userid);
MSG_WriteString (&buf, player->userinfo);
}
if (buf.cursize > MAX_QWMSGLEN/2)
if (buf.cursize)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
}
// send all current light styles
for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
{
if (i >= MAX_STANDARDLIGHTSTYLES)
if (!*cl_lightstyle[i].map)
continue;
// send current status of all other players
for (i = 0; i < cl.allocated_client_slots; i++)
{
player = cl.players + i;
if (player->frags != 0)
{
MSG_WriteByte (&buf, svc_updatefrags);
MSG_WriteByte (&buf, i);
MSG_WriteShort (&buf, player->frags);
}
if (player->ping != 0)
{
MSG_WriteByte (&buf, svc_updateping);
MSG_WriteByte (&buf, i);
MSG_WriteShort (&buf, player->ping);
}
if (player->pl != 0)
{
MSG_WriteByte (&buf, svc_updatepl);
MSG_WriteByte (&buf, i);
MSG_WriteByte (&buf, player->pl);
}
if (*player->userinfo)
{
MSG_WriteByte (&buf, svc_updateentertime);
MSG_WriteByte (&buf, i);
MSG_WriteFloat (&buf, player->entertime);
}
if (*player->userinfo)
{
MSG_WriteByte (&buf, svc_updateuserinfo);
MSG_WriteByte (&buf, i);
MSG_WriteLong (&buf, player->userid);
MSG_WriteString (&buf, player->userinfo);
}
if (buf.cursize > MAX_QWMSGLEN/2)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
}
// send all current light styles
for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
{
if (i >= MAX_STANDARDLIGHTSTYLES)
if (!*cl_lightstyle[i].map)
continue;
#ifdef PEXT_LIGHTSTYLECOL
if ((cls.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && cl_lightstyle[i].colour!=7 && *cl_lightstyle[i].map)
{
MSG_WriteByte (&buf, svcfte_lightstylecol);
MSG_WriteByte (&buf, (unsigned char)i);
MSG_WriteByte (&buf, cl_lightstyle[i].colour);
MSG_WriteString (&buf, cl_lightstyle[i].map);
}
else
if ((cls.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && cl_lightstyle[i].colour!=7 && *cl_lightstyle[i].map)
{
MSG_WriteByte (&buf, svcfte_lightstylecol);
MSG_WriteByte (&buf, (unsigned char)i);
MSG_WriteByte (&buf, cl_lightstyle[i].colour);
MSG_WriteString (&buf, cl_lightstyle[i].map);
}
else
#endif
{
MSG_WriteByte (&buf, svc_lightstyle);
MSG_WriteByte (&buf, (unsigned char)i);
MSG_WriteString (&buf, cl_lightstyle[i].map);
{
MSG_WriteByte (&buf, svc_lightstyle);
MSG_WriteByte (&buf, (unsigned char)i);
MSG_WriteString (&buf, cl_lightstyle[i].map);
}
}
}
for (i = ((cls.fteprotocolextensions&PEXT_HEXEN2)?MAX_QW_STATS:MAX_CL_STATS); i >= 0; i--)
{
if (!cl.playerview[0].stats[i])
continue;
MSG_WriteByte (&buf, svcqw_updatestatlong);
MSG_WriteByte (&buf, i);
MSG_WriteLong (&buf, cl.playerview[0].stats[i]);
if (buf.cursize > MAX_QWMSGLEN/2)
for (i = ((cls.fteprotocolextensions&PEXT_HEXEN2)?MAX_QW_STATS:MAX_CL_STATS); i >= 0; i--)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
if (!cl.playerview[0].stats[i])
continue;
MSG_WriteByte (&buf, svcqw_updatestatlong);
MSG_WriteByte (&buf, i);
MSG_WriteLong (&buf, cl.playerview[0].stats[i]);
if (buf.cursize > MAX_QWMSGLEN/2)
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
}
// get the client to check and download skins
// when that is completed, a begin command will be issued
MSG_WriteByte (&buf, svc_stufftext);
MSG_WriteString (&buf, va("skins\n") );
CL_WriteRecordDemoMessage (&buf, seq++);
CL_WriteSetDemoMessage();
// done
break;
default:
Con_Printf("Unable to begin demo recording with this network protocol\n");
CL_Stop_f();
break;
}
// get the client to check and download skins
// when that is completed, a begin command will be issued
MSG_WriteByte (&buf, svc_stufftext);
MSG_WriteString (&buf, va("skins\n") );
CL_WriteRecordDemoMessage (&buf, seq++);
CL_WriteSetDemoMessage();
// done
}
/*

View File

@ -59,6 +59,7 @@ static struct predicted_player
static void CL_LerpNetFrameState(int fsanim, framestate_t *fs, lerpents_t *le);
qboolean CL_PredictPlayer(lerpents_t *le, entity_state_t *state, int sequence);
void CL_PlayerFrameUpdated(player_state_t *plstate, entity_state_t *state, int sequence);
void CL_AckedInputFrame(int seq, qboolean worldstateokay);
extern int cl_playerindex, cl_h_playerindex, cl_rocketindex, cl_grenadeindex, cl_gib1index, cl_gib2index, cl_gib3index;
@ -737,8 +738,8 @@ void CLFTE_ParseEntities(void)
else if (cls.protocol == CP_NETQUAKE)
{
int i;
for (i = 0; i < MAX_SPLITS; i++)
cl.playerview[i].fixangle = false;
if (cls.demoplayback)
cls.netchan.incoming_unreliable++; //demo playback has no sequence info...
cls.netchan.incoming_sequence = cls.netchan.incoming_unreliable;
cl.last_servermessage = realtime;
if (cls.fteprotocolextensions2 & PEXT2_PREDINFO)
@ -753,6 +754,18 @@ void CLFTE_ParseEntities(void)
cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK].receivedtime = realtime;
{
extern vec3_t demoangles;
int fr = cls.netchan.incoming_sequence&UPDATE_MASK;
for (i = 0; i < MAX_SPLITS; i++)
cl.inframes[fr&UPDATE_MASK].packet_entities.fixangles[i] = false;
if (cls.demoplayback)
{
cl.inframes[fr&UPDATE_MASK].packet_entities.fixangles[0] = 2;
VectorCopy(demoangles, cl.inframes[fr&UPDATE_MASK].packet_entities.fixedangles[0]);
}
}
// if (cl.validsequence != cls.netchan.incoming_sequence-1)
// Con_Printf("CLIENT: Dropped a frame\n");
}
@ -885,13 +898,15 @@ void CLFTE_ParseEntities(void)
{
cl.oldvalidsequence = cl.validsequence;
cl.validsequence = cls.netchan.incoming_sequence;
cl.ackedmovesequence = inputframe;
CL_AckedInputFrame(inputframe, true);
cl.inframes[newpacket].invalid = false;
}
else
{
newp->num_entities = 0;
cl.validsequence = 0;
CL_AckedInputFrame(inputframe, false);
}
}
@ -978,9 +993,10 @@ void CLQW_ParsePacketEntities (qboolean delta)
full = true;
}
//FIXME
cl.oldvalidsequence = cl.validsequence;
cl.validsequence = cls.netchan.incoming_sequence;
cl.ackedmovesequence = cl.validsequence;
CL_AckedInputFrame(cls.netchan.incoming_sequence, true);
oldindex = 0;
newindex = 0;
@ -1293,12 +1309,14 @@ void CLDP_ParseDarkPlaces5Entities(void) //the things I do.. :o(
int oldi, newi, lowesti, lowestv, newremaining;
qboolean remove;
//server->client sequence
if (cl.numackframes == sizeof(cl.ackframes)/sizeof(cl.ackframes[0]))
cl.numackframes--;
cl.ackframes[cl.numackframes++] = MSG_ReadLong(); /*server sequence to be acked*/
//client->server sequence ack
if (cls.protocol_nq >= CPNQ_DP7)
cl.ackedmovesequence = MSG_ReadLong(); /*client input sequence which has been acked*/
CL_AckedInputFrame(MSG_ReadLong(), true); /*client input sequence which has been acked*/
cl.inframes[(cls.netchan.incoming_sequence)&UPDATE_MASK].receivedtime = realtime;
pack = &cl.inframes[(cls.netchan.incoming_sequence)&UPDATE_MASK].packet_entities;
@ -2713,7 +2731,7 @@ void R_FlameTrail(vec3_t start, vec3_t end, float seperation);
/*
Interpolates the two packets by the given time, writes its results into the lerpentities array.
*/
static void CL_TransitionPacketEntities(int newsequence, packet_entities_t *newpack, packet_entities_t *oldpack, float servertime)
static void CL_TransitionPacketEntities(int newsequence, packet_entities_t *newpack, packet_entities_t *oldpack, float frac, float servertime)
{
lerpents_t *le;
entity_state_t *snew, *sold;
@ -2724,7 +2742,6 @@ static void CL_TransitionPacketEntities(int newsequence, packet_entities_t *newp
float a1, a2;
float frac;
/*
seeing as how dropped packets cannot be filled in due to the reliable networking stuff,
We can simply detect changes and lerp towards them
@ -2734,11 +2751,6 @@ static void CL_TransitionPacketEntities(int newsequence, packet_entities_t *newp
//we figure out which ones are new,
//we don't care about old, as our caller will use the lerpents array we fill, and the entity numbers from the 'new' packet.
if (newpack->servertime == oldpack->servertime)
frac = 1; //lerp totally into the new
else
frac = (servertime-oldpack->servertime)/(newpack->servertime-oldpack->servertime);
cl.lerpentssequence = newsequence;
oldpnum=0;
@ -2953,7 +2965,7 @@ void CL_TransitionEntities (void)
packet_entities_t *packnew, *packold;
int newf, newff, oldf;
qboolean nolerp;
float servertime;
float servertime, frac;
if (cls.protocol == CP_QUAKEWORLD && (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV))
{
@ -2982,13 +2994,19 @@ void CL_TransitionEntities (void)
/*transition the ents and stuff*/
packnew = &cl.inframes[newf].packet_entities;
packold = &cl.inframes[oldf].packet_entities;
if (packnew->servertime == packold->servertime)
frac = 1; //lerp totally into the new
else
frac = (servertime-packold->servertime)/(packnew->servertime-packold->servertime);
// Con_Printf("%f %f %f (%i)\n", packold->servertime, servertime, packnew->servertime, newff);
// Con_Printf("%f %f %f (%f) (%i)\n", packold->servertime, servertime, packnew->servertime, frac, newff);
// Con_Printf("%f %f %f\n", cl.oldgametime, servertime, cl.gametime);
CL_TransitionPacketEntities(newff, packnew, packold, servertime);
CL_TransitionPacketEntities(newff, packnew, packold, frac, servertime);
cl.packfrac = frac;
cl.currentpacktime = servertime;
cl.currentpackentities = packnew;
cl.previouspackentities = packold;
/*and transition players too*/
@ -2998,7 +3016,7 @@ void CL_TransitionEntities (void)
vec3_t move;
lerpents_t *le;
player_state_t *pnew, *pold;
if (!cl_lerp_players.ival && !(cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV))
if (!cl.do_lerp_players)
{
newf = newff = oldf = cl.parsecount;
newf&=UPDATE_MASK;
@ -3966,7 +3984,7 @@ guess_pm_type:
}
}
if (cl.worldmodel && cl_lerp_players.ival)
if (cl.worldmodel && cl.do_lerp_players)
{
player_state_t exact;
msec += cls.latency*1000;
@ -4316,7 +4334,7 @@ void CL_LinkPlayers (void)
if (pnum < cl.splitclients)
{ //this is a local player
}
else if (cl_lerp_players.ival || (cls.demoplayback==DPB_MVD || cls.demoplayback == DPB_EZTV))
else if (cl.do_lerp_players)
{
lerpents_t *le = &cl.lerpplayers[j];
VectorCopy (le->origin, ent->origin);

View File

@ -610,6 +610,12 @@ void CL_ClampPitch (int pnum)
static float oldtime;
float timestep = realtime - oldtime;
oldtime = realtime;
if (cl.intermission)
{
memset(cl.playerview[pnum].viewanglechange, 0, sizeof(cl.playerview[pnum].viewanglechange));
return;
}
#if 0
if (cl.pmovetype[pnum] == PM_WALLWALK)
{
@ -650,7 +656,7 @@ void CL_ClampPitch (int pnum)
}
#endif
#if 1
if ((cl.playerview[pnum].gravitydir[2] != -1 || cl.playerview[pnum].viewangles[2]) && !cl.playerview[pnum].fixangles && !cl.intermission)
if ((cl.playerview[pnum].gravitydir[2] != -1 || cl.playerview[pnum].viewangles[2]))
{
float surfm[16], invsurfm[16];
float viewm[16];
@ -769,8 +775,6 @@ void CL_ClampPitch (int pnum)
else
#endif
{
if (cl.playerview[pnum].fixangle)
return;
if (cl.playerview[pnum].viewangles[PITCH] > cl.maxpitch)
cl.playerview[pnum].viewangles[PITCH] = cl.maxpitch;
if (cl.playerview[pnum].viewangles[PITCH] < cl.minpitch)

View File

@ -630,10 +630,13 @@ void CL_CheckForResend (void)
char data[2048];
double t1, t2;
int contype = 0;
unsigned int pext1, pext2;
#ifndef CLIENTONLY
if (!cls.state && sv.state)
{
pext1 = 0;
pext2 = 0;
Q_strncpyz (cls.servername, "internalserver", sizeof(cls.servername));
Cvar_ForceSet(&cl_servername, cls.servername);
@ -642,17 +645,27 @@ void CL_CheckForResend (void)
{
#ifdef Q3CLIENT
case GT_QUAKE3:
pext1 = 0;
pext2 = 0;
cls.protocol = CP_QUAKE3;
break;
#endif
#ifdef Q2CLIENT
case GT_QUAKE2:
pext1 = 0;
pext2 = 0;
cls.protocol = CP_QUAKE2;
break;
#endif
default:
cl.movesequence = 0;
if (!strcmp(cl_loopbackprotocol.string, "qw"))
{
pext1 = Net_PextMask(1, false);
pext2 = Net_PextMask(2, false);
cls.protocol = CP_QUAKEWORLD;
}
else if (!strcmp(cl_loopbackprotocol.string, "idqw"))
cls.protocol = CP_QUAKEWORLD;
else if (!strcmp(cl_loopbackprotocol.string, "fitz")) //actually proquake, because we might as well use the extra angles
{
@ -682,9 +695,26 @@ void CL_CheckForResend (void)
cls.protocol_nq = CPNQ_DP7;
}
else if (progstype == PROG_QW)
{
cls.protocol = CP_QUAKEWORLD;
pext1 = Net_PextMask(1, false);
pext2 = Net_PextMask(2, false);
}
else
cls.protocol = CP_NETQUAKE;
//make sure the protocol within demos is actually correct/sane
if (cls.demorecording == 1 && cls.protocol != CP_QUAKEWORLD)
{
cls.protocol = CP_QUAKEWORLD;
pext1 = Net_PextMask(1, false);
pext2 = Net_PextMask(2, false);
}
else if (cls.demorecording == 2 && cls.protocol != CP_NETQUAKE)
{
cls.protocol = CP_NETQUAKE;
cls.protocol_nq = CPNQ_FITZ666;
}
break;
}
@ -701,7 +731,7 @@ void CL_CheckForResend (void)
}
NET_AdrToString(data, sizeof(data), &adr);
/*eat up the server's packets, to clear any lingering loopback packets*/
/*eat up the server's packets, to clear any lingering loopback packets (like disconnect commands... yes this might cause packetloss for other clients)*/
while(NET_GetPacket (NS_SERVER, 0) >= 0)
{
}
@ -733,7 +763,7 @@ void CL_CheckForResend (void)
CL_ConnectToDarkPlaces("", &adr);
}
else
CL_SendConnectPacket (8192-16, Net_PextMask(1, false), Net_PextMask(2, false), false);
CL_SendConnectPacket (8192-16, pext1, pext2, false);
return;
}
#endif
@ -2686,7 +2716,7 @@ void CLNQ_ConnectionlessPacket(void)
#endif
void CL_MVDUpdateSpectator (void);
void CL_WriteDemoMessage (sizebuf_t *msg);
void CL_WriteDemoMessage (sizebuf_t *msg, int payloadoffset);
/*
=================
CL_ReadPackets
@ -2776,6 +2806,7 @@ void CL_ReadPackets (void)
// cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence - 3;
case NQP_RELIABLE://reliable
MSG_ChangePrimitives(cls.netchan.netprim);
CL_WriteDemoMessage (&net_message, msg_readcount);
CLNQ_ParseServerMessage ();
break;
}
@ -2805,7 +2836,7 @@ void CL_ReadPackets (void)
else if (!Netchan_Process(&cls.netchan))
continue; // wasn't accepted for some reason
CL_WriteDemoMessage (&net_message);
CL_WriteDemoMessage (&net_message, msg_readcount);
if (cls.netchan.incoming_sequence > cls.netchan.outgoing_sequence)
{ //server should not be responding to packets we have not sent yet
@ -4103,6 +4134,7 @@ double Host_Frame (double time)
CL_UseIndepPhysics(!!cl_threadedphysics.ival);
cl.do_lerp_players = cl_lerp_players.ival || (cls.demoplayback==DPB_MVD || cls.demoplayback == DPB_EZTV) || (cls.demoplayback && !cl_nolerp.ival);
CL_AllowIndependantSendCmd(false);
// fetch results from server

View File

@ -210,21 +210,21 @@ char *svc_nqstrings[] =
"nqsvc_sellscreen",
"nqsvc_cutscene", //34
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL", //40
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL",
"NEW PROTOCOL", //35
"NEW PROTOCOL", //36
"fitzsvc_skybox", //37
"NEW PROTOCOL", //38
"NEW PROTOCOL", //39
"fitzsvc_bf", //40
"fitzsvc_fog", //41
"fitzsvc_spawnbaseline2", //42
"fitzsvc_spawnstatic2", //43
"fitzsvc_spawnstaticsound2", //44
"NEW PROTOCOL", //45
"NEW PROTOCOL", //46
"NEW PROTOCOL", //47
"NEW PROTOCOL", //48
"NEW PROTOCOL", //49
"dpsvc_downloaddata", //50
"dpsvc_updatestatubyte", //51
"dpsvc_effect", //52
@ -238,33 +238,32 @@ char *svc_nqstrings[] =
"dpsvc_trailparticles", //60
"dpsvc_pointparticles", //61
"dpsvc_pointparticles1", //62
"NEW PROTOCOL(63)",
"NEW PROTOCOL(64)",
"NEW PROTOCOL(65)",
"nqsvcfte_spawnbaseline2(66)", //66
"NEW PROTOCOL(67)",
"NEW PROTOCOL(68)",
"NEW PROTOCOL(69)",
"NEW PROTOCOL(70)",
"NEW PROTOCOL(71)",
"NEW PROTOCOL(72)",
"NEW PROTOCOL(73)",
"NEW PROTOCOL(74)",
"NEW PROTOCOL(75)",
"NEW PROTOCOL(76)",
"NEW PROTOCOL(77)",
"NEW PROTOCOL(78)",
"NEW PROTOCOL(79)",
"NEW PROTOCOL(80)",
"NEW PROTOCOL(81)",
"NEW PROTOCOL(82)",
"NEW PROTOCOL(83)",
"NEW PROTOCOL(84)",
"NEW PROTOCOL(85)",
"nqsvcfte_updateentities(86)",
"NEW PROTOCOL(87)",
"NEW PROTOCOL(88)",
"NEW PROTOCOL(63)", //63
"NEW PROTOCOL(64)", //64
"NEW PROTOCOL(65)", //65
"ftenqsvc_spawnbaseline2", //66
"NEW PROTOCOL(67)", //67
"NEW PROTOCOL(68)", //68
"NEW PROTOCOL(69)", //69
"NEW PROTOCOL(70)", //70
"NEW PROTOCOL(71)", //71
"NEW PROTOCOL(72)", //72
"NEW PROTOCOL(73)", //73
"NEW PROTOCOL(74)", //74
"NEW PROTOCOL(75)", //75
"NEW PROTOCOL(76)", //76
"NEW PROTOCOL(77)", //77
"NEW PROTOCOL(78)", //78
"NEW PROTOCOL(79)", //79
"NEW PROTOCOL(80)", //80
"NEW PROTOCOL(81)", //81
"NEW PROTOCOL(82)", //82
"NEW PROTOCOL(83)", //83
"NEW PROTOCOL(84)", //84
"NEW PROTOCOL(85)", //85
"nqsvcfte_updateentities", //86
"NEW PROTOCOL(87)", //87
"NEW PROTOCOL(88)" //88
};
extern cvar_t requiredownloads, cl_standardchat, msg_filter, cl_countpendingpl, cl_download_mapsrc;
@ -324,12 +323,12 @@ int CL_CalcNet (void)
sent = NET_TIMINGS;
for (i=cls.netchan.outgoing_sequence-UPDATE_BACKUP+1
; i <= cls.netchan.outgoing_sequence
for (i=cl.movesequence-UPDATE_BACKUP+1
; i <= cl.movesequence
; i++)
{
frame = &cl.inframes[i&UPDATE_MASK];
if (i > cl.parsecount)
if (i > cl.lastackedmovesequence)
{
// no response yet
if (cl_countpendingpl.ival)
@ -366,6 +365,42 @@ int CL_CalcNet (void)
return percent;
}
void CL_AckedInputFrame(int seq, qboolean worldstateokay)
{
unsigned int i;
unsigned int newmod;
inframe_t *frame;
newmod = seq & UPDATE_MASK;
frame = &cl.inframes[newmod];
// calculate latency
frame->latency = realtime - cl.outframes[newmod].senttime;
if (frame->latency < 0 || frame->latency > 1.0)
{
// Con_Printf ("Odd latency: %5.2f\n", latency);
}
else
{
// drift the average latency towards the observed latency
if (frame->latency < cls.latency)
cls.latency = frame->latency;
else
cls.latency += 0.001; // drift up, so correction are needed
}
//and mark any missing ones as dropped
if (seq != cl.lastackedmovesequence)
{
for (i = (cl.lastackedmovesequence+1) & UPDATE_MASK; i != newmod; i=(i+1)&UPDATE_MASK)
{
cl.inframes[i].latency = -1;
}
}
if (worldstateokay)
cl.ackedmovesequence = seq;
cl.lastackedmovesequence = seq;
}
//=============================================================================
//note: this will overwrite existing files.
@ -2729,21 +2764,10 @@ void CL_ParseEstablished(void)
}
#ifdef NQPROT
//FIXME: move to header
void CL_KeepaliveMessage(void){}
void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
void CLNQ_ParseProtoVersion(void)
{
int nummodels, numsounds;
char *str;
int gametype;
int protover;
struct netprim_s netprim;
if (developer.ival)
Con_TPrintf (TLC_GOTSVDATAPACKET);
SCR_SetLoadingStage(LS_CLIENT);
CL_ClearState ();
Stats_NewMap();
Cvar_ForceCallback(Cvar_FindVar("r_particlesdesc"));
cls.fteprotocolextensions = 0;
cls.fteprotocolextensions2 = 0;
@ -2848,6 +2872,23 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
}
cls.netchan.message.prim = cls.netchan.netprim = netprim;
MSG_ChangePrimitives(netprim);
}
//FIXME: move to header
void CL_KeepaliveMessage(void){}
void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution.
{
int nummodels, numsounds;
char *str;
int gametype;
if (developer.ival)
Con_TPrintf (TLC_GOTSVDATAPACKET);
SCR_SetLoadingStage(LS_CLIENT);
CL_ClearState ();
Stats_NewMap();
Cvar_ForceCallback(Cvar_FindVar("r_particlesdesc"));
CLNQ_ParseProtoVersion();
if (MSG_ReadByte() > MAX_CLIENTS)
{
@ -3575,14 +3616,22 @@ void CL_ParseStatic (int version)
entity_state_t es;
vec3_t mins,maxs;
if (version == 1)
if (version == 3)
{
CLFitz_ParseBaseline2(&es);
i = cl.num_statics;
cl.num_statics++;
}
else if (version == 1)
{
//old nq/qw style
CL_ParseBaseline (&es);
i = cl.num_statics;
cl.num_statics++;
}
else
else if (version == 2)
{
//new deltaed style ('full' extension support)
if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS)
CLFTE_ParseBaseline(&es, false);
else
@ -3605,6 +3654,8 @@ void CL_ParseStatic (int version)
cl.num_statics++;
}
}
else
return;
if (i == cl_max_static_entities)
{
@ -3926,13 +3977,14 @@ Server information pertaining to this client only, sent every frame
void CL_ParseClientdata (void)
{
int i;
inframe_t *frame;
// calculate simulated time of message
oldparsecountmod = parsecountmod;
i = cls.netchan.incoming_acknowledged;
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
if (cls.demoplayback == DPB_NETQUAKE)
i = cls.netchan.incoming_sequence-1;
if (cls.demoplayback == DPB_NETQUAKE || cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{
cl.oldparsecount = i - 1;
oldparsecountmod = cl.oldparsecount & UPDATE_MASK;
@ -3940,32 +3992,10 @@ void CL_ParseClientdata (void)
cl.parsecount = i;
i &= UPDATE_MASK;
parsecountmod = i;
frame = &cl.inframes[i];
// if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
// frame->senttime = realtime - host_frametime;
parsecounttime = cl.outframes[i].senttime;
// calculate latency
frame->latency = realtime - parsecounttime;
//and mark any missing ones as dropped
for (i = (oldparsecountmod+1)&UPDATE_MASK; i != parsecountmod; i=((i+1)&UPDATE_MASK))
{
cl.inframes[i].latency = -1;
}
if (frame->latency < 0 || frame->latency > 1.0)
{
// Con_Printf ("Odd latency: %5.2f\n", latency);
}
else
{
// drift the average latency towards the observed latency
if (frame->latency < cls.latency)
cls.latency = frame->latency;
else
cls.latency += 0.001; // drift up, so correction are needed
}
if (cls.protocol == CP_QUAKEWORLD)
CL_AckedInputFrame(cl.parsecount, false);
}
/*
@ -4211,11 +4241,49 @@ static void CL_SetStat_Internal (int pnum, int stat, int value)
}
cl.playerview[pnum].stats[stat] = value;
cl.playerview[pnum].statsf[stat] = value;
if (pnum == 0)
TP_StatChanged(stat, value);
}
void CL_SetStatMovevar(int pnum, int stat, float value)
{
switch(stat)
{
case STAT_MOVEVARS_GRAVITY:
movevars.gravity = value;
break;
case STAT_MOVEVARS_STOPSPEED:
movevars.stopspeed = value;
break;
case STAT_MOVEVARS_MAXSPEED:
cl.playerview[pnum].maxspeed = value;
break;
case STAT_MOVEVARS_SPECTATORMAXSPEED:
movevars.spectatormaxspeed = value;
break;
case STAT_MOVEVARS_ACCELERATE:
movevars.accelerate = value;
break;
case STAT_MOVEVARS_AIRACCELERATE:
movevars.airaccelerate = value;
break;
case STAT_MOVEVARS_WATERACCELERATE:
movevars.wateraccelerate = value;
break;
case STAT_MOVEVARS_FRICTION:
movevars.friction = value;
break;
case STAT_MOVEVARS_WATERFRICTION:
movevars.waterfriction = value;
break;
case STAT_MOVEVARS_ENTGRAVITY:
cl.playerview[pnum].entgravity = value;
break;
}
}
void CL_SetStatInt (int pnum, int stat, int value)
{
if (stat < 0 || stat >= MAX_CL_STATS)
@ -4235,6 +4303,7 @@ void CL_SetStatInt (int pnum, int stat, int value)
{
extern int cls_lastto;
cl.players[cls_lastto].stats[stat]=value;
cl.players[cls_lastto].statsf[stat]=value;
for (pnum = 0; pnum < cl.splitclients; pnum++)
if (cl.playerview[pnum].cam_spec_track == cls_lastto)
@ -4242,6 +4311,9 @@ void CL_SetStatInt (int pnum, int stat, int value)
}
else
CL_SetStat_Internal(pnum, stat, value);
if (cls.protocol == CP_NETQUAKE && CPNQ_IS_DP && !(cls.fteprotocolextensions2 & PEXT2_PREDINFO))
CL_SetStatMovevar(pnum, stat, *(float*)&value); //DP sucks.
}
void CL_SetStatFloat (int pnum, int stat, float value)
{
@ -4253,16 +4325,26 @@ void CL_SetStatFloat (int pnum, int stat, float value)
{
extern int cls_lastto;
cl.players[cls_lastto].statsf[stat]=value;
cl.players[cls_lastto].stats[stat]=value;
for (pnum = 0; pnum < cl.splitclients; pnum++)
if (cl.playerview[pnum].cam_spec_track == cls_lastto)
{
cl.playerview[pnum].statsf[stat] = value;
cl.playerview[pnum].stats[stat] = value;
}
}
else
{
cl.playerview[pnum].statsf[stat] = value;
cl.playerview[pnum].stats[stat] = value;
}
if (stat == STAT_VIEWHEIGHT && cls.z_ext & Z_EXT_VIEWHEIGHT)
cl.playerview[pnum].viewheight = value;
if (cls.fteprotocolextensions2 & PEXT2_PREDINFO)
CL_SetStatMovevar(pnum, stat, value);
}
void CL_SetStatString (int pnum, int stat, char *value)
{
@ -5258,12 +5340,22 @@ void CLQW_ParseServerMessage (void)
int destsplit;
float f;
qboolean csqcpacket = false;
inframe_t *inf;
extern vec3_t demoangles;
received_framecount = host_framecount;
cl.last_servermessage = realtime;
CL_ClearProjectiles ();
for (i = 0; i < MAX_SPLITS; i++)
cl.playerview[i].fixangle = false;
//clear out fixangles stuff
inf = &cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK];
for (j = 0; j < MAX_SPLITS; j++)
inf->packet_entities.fixangles[j] = false;
if (cls.demoplayback == DPB_QUAKEWORLD)
{
inf->packet_entities.fixangles[0] = 2;
VectorCopy(demoangles, inf->packet_entities.fixedangles[0]);
}
//
// if recording demos, copy the message out
@ -5411,11 +5503,12 @@ void CLQW_ParseServerMessage (void)
case svcfte_setangledelta:
for (i=0 ; i<3 ; i++)
cl.playerview[destsplit].viewangles[i] += MSG_ReadAngle16 ();
VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].simangles);
// VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].simangles);
break;
case svc_setangle:
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
{
//I really don't get the point of fixangles in an mvd. to disable interpolation for that frame?
vec3_t ang;
i = MSG_ReadByte();
for (i=0 ; i<3 ; i++)
@ -5425,20 +5518,17 @@ void CLQW_ParseServerMessage (void)
playerview_t *pv = &cl.playerview[j];
if (Cam_TrackNum(pv) == i)
{
pv->fixangle=true;
VectorCopy(ang, pv->simangles);
VectorCopy(ang, pv->viewangles);
VectorCopy(ang, pv->fixangles);
inf->packet_entities.fixangles[j] = true;
VectorCopy(ang, inf->packet_entities.fixedangles[j]);
}
}
break;
}
cl.playerview[destsplit].fixangle=true;
inf->packet_entities.fixangles[destsplit] = true;
for (i=0 ; i<3 ; i++)
cl.playerview[destsplit].viewangles[i] = cl.playerview[destsplit].fixangles[i] = MSG_ReadAngle ();
VectorCopy (cl.playerview[destsplit].viewangles, cl.playerview[destsplit].simangles);
// cl.playerview[destsplit].viewangles[PITCH] = cl.viewangles[ROLL] = 0;
{
cl.playerview[destsplit].viewangles[i] = cl.playerview[destsplit].intermissionangles[i] = inf->packet_entities.fixedangles[destsplit][i] = MSG_ReadAngle ();
}
break;
case svc_lightstyle:
@ -5604,16 +5694,16 @@ void CLQW_ParseServerMessage (void)
for (i=0 ; i<3 ; i++)
cl.playerview[destsplit].simorg[i] = MSG_ReadCoord ();
for (i=0 ; i<3 ; i++)
cl.playerview[destsplit].simangles[i] = MSG_ReadAngle ();
VectorCopy (cl.playerview[destsplit].simangles, cl.playerview[destsplit].fixangles);
VectorClear (cl.playerview[destsplit].simvel);
cl.playerview[destsplit].intermissionangles[i] = MSG_ReadAngle ();
break;
case svc_finale:
if (!cl.intermission)
{
for (i = 0; i < MAX_SPLITS; i++)
cl.playerview[i].simorg[2] += cl.playerview[i].viewheight;
VectorCopy (cl.playerview[destsplit].fixangles, cl.playerview[destsplit].simangles);
VectorCopy (cl.playerview[destsplit].simangles, cl.playerview[destsplit].intermissionangles);
}
cl.intermission = 2;
cl.completed_time = cl.gametime;
@ -6174,7 +6264,7 @@ void CLNQ_ParseServerMessage (void)
case svc_disconnect:
CL_Disconnect();
break;
return;
case svc_centerprint:
s = MSG_ReadString ();
@ -6222,6 +6312,9 @@ void CLNQ_ParseServerMessage (void)
}
break;
case svc_version:
CLNQ_ParseProtoVersion();
break;
case svc_serverdata:
Cbuf_Execute (); // make sure any stuffed commands are done
CLNQ_ParseServerData ();
@ -6301,9 +6394,15 @@ void CLNQ_ParseServerMessage (void)
case svc_time:
//fixme: move this stuff to a common place
cl.playerview[destsplit].oldfixangle = cl.playerview[destsplit].fixangle;
VectorCopy(cl.playerview[destsplit].fixangles, cl.playerview[destsplit].oldfixangles);
cl.playerview[destsplit].fixangle = false;
// cl.playerview[destsplit].oldfixangle = cl.playerview[destsplit].fixangle;
// VectorCopy(cl.playerview[destsplit].fixangles, cl.playerview[destsplit].oldfixangles);
// cl.playerview[destsplit].fixangle = false;
if (cls.demoplayback)
{
// extern vec3_t demoangles;
// cl.playerview[destsplit].fixangle = true;
// VectorCopy(demoangles, cl.playerview[destsplit].fixangles);
}
cls.netchan.outgoing_sequence++;
cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence-1;
@ -6317,7 +6416,18 @@ void CLNQ_ParseServerMessage (void)
cl.gametime = MSG_ReadFloat();
cl.gametimemark = realtime;
cl.inframes[cl.validsequence&UPDATE_MASK].receivedtime = realtime;
{
extern vec3_t demoangles;
int fr = cls.netchan.incoming_sequence&UPDATE_MASK;
if (cls.demoplayback)
{
cl.inframes[fr&UPDATE_MASK].packet_entities.fixangles[destsplit] = true;
VectorCopy(demoangles, cl.inframes[fr&UPDATE_MASK].packet_entities.fixedangles[destsplit]);
}
else
cl.inframes[fr&UPDATE_MASK].packet_entities.fixangles[destsplit] = false;
}
cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK].receivedtime = realtime;
if (CPNQ_IS_DP)
{
@ -6409,13 +6519,15 @@ void CLNQ_ParseServerMessage (void)
CL_SetStatFloat (0, i, j);
break;
case svc_setangle:
cl.playerview[destsplit].fixangle=true;
for (i=0 ; i<3 ; i++)
cl.playerview[destsplit].viewangles[i] = cl.playerview[destsplit].fixangles[i] = MSG_ReadAngle ();
// cl.viewangles[PITCH] = cl.viewangles[ROLL] = 0;
{
inframe_t *inf = &cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK];
inf->packet_entities.fixangles[destsplit] = true;
for (i=0 ; i<3 ; i++)
cl.playerview[destsplit].viewangles[i] = cl.playerview[destsplit].intermissionangles[i] = inf->packet_entities.fixedangles[destsplit][i] = MSG_ReadAngle ();
}
break;
case svc_clientdata:
case svcnq_clientdata:
CLNQ_ParseClientdata ();
break;
@ -6495,10 +6607,12 @@ void CLNQ_ParseServerMessage (void)
Host_EndGame("CLNQ_ParseServerMessage: svcfitz_spawnbaseline2 failed with ent %i", i);
CLFitz_ParseBaseline2 (cl_baselines + i);
break;
// case svcfitz_spawnstatic2:
// break;
// case svcfitz_spawnstaticsound2:
// break;
case svcfitz_spawnstatic2:
CL_ParseStatic (3);
break;
case svcfitz_spawnstaticsound2:
Host_EndGame("svcfitz_spawnstaticsound2: not implemented");
break;
case svcnq_effect:

View File

@ -21,7 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "winquake.h"
cvar_t cl_nopred = SCVAR("cl_nopred","0");
extern cvar_t cl_lerp_players;
cvar_t cl_pushlatency = SCVAR("pushlatency","-999");
extern float pm_airaccelerate;
@ -504,7 +503,7 @@ void CL_CalcCrouch (playerview_t *pv, float stepchange)
float LerpAngles360(float to, float from, float frac)
{
int delta;
float delta;
delta = (from-to);
if (delta > 180)
@ -636,6 +635,7 @@ short LerpAngles16(short to, short from, float frac)
void CL_CalcClientTime(void)
{
extern float demtime;
if (cls.protocol != CP_QUAKE3)
{
float oldst = realtime;
@ -670,7 +670,13 @@ void CL_CalcClientTime(void)
max = min;
if (max)
cl.servertime += host_frametime;
{
extern cvar_t cl_demospeed;
if (cls.demoplayback && cl_demospeed.value >= 0 && cls.state == ca_active)
cl.servertime += host_frametime*cl_demospeed.value;
else
cl.servertime += host_frametime;
}
else
cl.servertime = 0;
@ -836,6 +842,7 @@ void CL_PlayerFrameUpdated(player_state_t *plstate, entity_state_t *state, int s
{
cl.playerview[i].stats[STAT_WEAPONFRAME] = state->u.q1.weaponframe;
cl.playerview[i].statsf[STAT_WEAPONFRAME] = state->u.q1.weaponframe;
cl.playerview[i].pmovetype = pmtype;
}
}
@ -908,6 +915,7 @@ void CL_PredictMovePNum (int seat)
float *org;
float stepheight = 0;
float netfps = cl_netfps.value;
if (!netfps)
{
//every video frame has its own input frame.
@ -951,39 +959,39 @@ void CL_PredictMovePNum (int seat)
if (cl.paused && !(cls.demoplayback!=DPB_MVD && cls.demoplayback!=DPB_EZTV) && (!cl.spectator || !pv->cam_auto))
return;
if (cl.intermission==1 && cls.protocol == CP_QUAKEWORLD)
{
pv->crouch = 0;
return;
}
#ifdef NQPROT
if (cls.protocol == CP_NETQUAKE && !(cls.fteprotocolextensions2 & PEXT2_PREDINFO))
{
cl.ackedmovesequence = cl.movesequence;
}
#endif
if (!cl.validsequence)
{
return;
}
if (cl.movesequence - cl.ackedmovesequence >= UPDATE_BACKUP-1)
{ //lagging like poo.
if (!cl.intermission) //keep the angles working though.
VectorCopy (pv->viewangles, pv->simangles);
if (cl.intermission==1 && cls.protocol == CP_QUAKEWORLD)
{
VectorCopy (pv->intermissionangles, pv->simangles);
return;
}
else
{
if (cl.currentpackentities && cl.currentpackentities->fixangles[seat])
{
if (cl.previouspackentities && cl.previouspackentities->fixangles[seat]==cl.currentpackentities->fixangles[seat])
{
for (i = 0; i < 3; i++)
pv->simangles[i] = LerpAngles360(cl.currentpackentities->fixedangles[seat][i], cl.previouspackentities->fixedangles[seat][i], 1-(cl.previouspackentities->fixangles[seat]?cl.packfrac:1));
}
else
VectorCopy(cl.currentpackentities->fixedangles[seat], pv->simangles);
}
else
VectorCopy (pv->viewangles, pv->simangles);
}
// this is the last frame received from the server
//don't wrap
if (cl.movesequence - cl.ackedmovesequence >= UPDATE_BACKUP-1)
return;
// this is the last frame received from the server
from = &cl.inframes[cl.validsequence & UPDATE_MASK];
cmdfrom = &cl.outframes[cl.ackedmovesequence & UPDATE_MASK];
if (!cl.intermission)
{
VectorCopy (pv->viewangles, pv->simangles);
}
vel = from->playerstate[pv->playernum].velocity;
org = from->playerstate[pv->playernum].origin;
@ -1018,16 +1026,23 @@ void CL_PredictMovePNum (int seat)
}
if (((cl_nopred.value && cls.demoplayback!=DPB_MVD && cls.demoplayback != DPB_EZTV)|| pv->fixangle || cl.paused))
if (((cl_nopred.value && cls.demoplayback!=DPB_MVD && cls.demoplayback != DPB_EZTV) || cl.paused || pv->pmovetype == PM_NONE))
{
if (cl_lerp_players.ival && !cls.demoplayback)
if (cl.do_lerp_players)
{
lerpents_t *le;
if (pv->nolocalplayer)
le = &cl.lerpents[pv->cam_spec_track+1];
lerpents_t *le = NULL;
if (pv->nolocalplayer)
{
if (pv->viewentity < cl.maxlerpents)
le = &cl.lerpents[pv->viewentity];
}
else
le = &cl.lerpplayers[pv->cam_spec_track];
org = le->origin;
{
if (pv->viewentity >= 1 && pv->viewentity <= MAX_CLIENTS)
le = &cl.lerpplayers[pv->viewentity-1];
}
if (le)
org = le->origin;
vel = vec3_origin;
}
@ -1056,7 +1071,7 @@ fixedorg:
if (pv->viewentity && pv->viewentity != pv->playernum+1 && CL_MayLerp())
{
float f;
if (cl_lerp_players.ival && (cls.demoplayback==DPB_MVD || cls.demoplayback == DPB_EZTV))
if (cl.do_lerp_players)
{
lerpents_t *le = &cl.lerpplayers[pv->cam_spec_track];
org = le->origin;

View File

@ -396,7 +396,7 @@ typedef struct
// demo recording info must be here, because record is started before
// entering a map (and clearing client_state_t)
qboolean demorecording;
int demorecording; //1=QW, 2=NQ
vfsfile_t *demooutfile;
enum{DPB_NONE,DPB_QUAKEWORLD,DPB_MVD,DPB_EZTV,
@ -518,8 +518,9 @@ struct playerview_s
// the client maintains its own idea of view angles, which are
// sent to the server each frame. And only reset at level change
// and teleport times
vec3_t viewangles;
vec3_t viewanglechange;
vec3_t viewangles; //current angles
vec3_t viewanglechange; //angles set by input code this frame
vec3_t intermissionangles; //absolute angles for intermission
vec3_t gravitydir;
// pitch drifting vars
@ -545,10 +546,6 @@ struct playerview_s
int waterlevel; //for smartjump
float punchangle; // temporary view kick from weapon firing
qboolean fixangle; //received a fixangle - so disable prediction till the next packet.
qboolean oldfixangle; //received a fixangle - so disable prediction till the next packet.
vec3_t fixangles; //received a fixangle - so disable prediction till the next packet.
vec3_t oldfixangles; //received a fixangle - so disable prediction till the next packet.
float v_dmg_time; //various view knockbacks.
float v_dmg_roll;
@ -601,10 +598,11 @@ typedef struct
int oldparsecount;
int oldvalidsequence;
int ackedmovesequence; //in quakeworld/q2 this is always equal to validsequence. nq can differ. may only be updated when validsequence is updated.
int lastackedmovesequence; //can be higher than ackedmovesequence when the received frame was unusable.
int validsequence; // this is the sequence number of the last good
// packetentity_t we got. If this is 0, we can't
// render a frame yet
int movesequence; //
int movesequence; // client->server frames
int spectator;
@ -723,8 +721,12 @@ typedef struct
float predicted_step_time;
float predicted_step;
//interpolation+snapshots
float packfrac;
packet_entities_t *currentpackentities;
packet_entities_t *previouspackentities;
float currentpacktime;
qboolean do_lerp_players;
int teamplay;
@ -1393,6 +1395,7 @@ void Stats_NewMap(void);
enum uploadfmt;
typedef struct
{
char *drivername;
void *(VARGS *createdecoder)(char *name);
void *(VARGS *decodeframe)(void *ctx, qboolean nosound, enum uploadfmt *fmt, int *width, int *height);
void (VARGS *doneframe)(void *ctx, void *img);
@ -1407,6 +1410,7 @@ typedef struct
void (VARGS *changestream) (void *ctx, char *streamname);
} media_decoder_funcs_t;
typedef struct {
char *drivername;
void *(VARGS *capture_begin) (char *streamname, int videorate, int width, int height, int *sndkhz, int *sndchannels, int *sndbits);
void (VARGS *capture_video) (void *ctx, void *data, int frame, int width, int height);
void (VARGS *capture_audio) (void *ctx, void *data, int bytes);

View File

@ -484,6 +484,7 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu
range = 0;
if (range > 1)
range = 1;
option->slider.vx = x;
x -= 8;
Font_BeginString(font_conchar, x, y, &x, &y);
x = Font_DrawChar(x, y, 0xe080 | CON_WHITEMASK);
@ -1252,6 +1253,9 @@ void MC_Slider_Key(menuslider_t *option, int key)
float range = option->current;
float delta;
float ix = option->vx;
float ex = ix + 10*8;
if (option->smallchange)
delta = option->smallchange;
else
@ -1263,8 +1267,6 @@ void MC_Slider_Key(menuslider_t *option, int key)
if (range < option->min)
range = option->min;
option->current = range;
if (option->var)
Cvar_SetValue(option->var, range);
}
else if (key == K_RIGHTARROW || key == K_MWHEELUP)
{
@ -1272,8 +1274,12 @@ void MC_Slider_Key(menuslider_t *option, int key)
if (range > option->max)
range = option->max;
option->current = range;
if (option->var)
Cvar_SetValue(option->var, range);
}
else if (key == K_MOUSE1 && mousecursor_x >= ix-8 && mousecursor_x < ex+8)
{
range = (mousecursor_x - ix) / (ex - ix);
range = option->min + range*(option->max-option->min);
option->current = range;
}
else if (key == K_ENTER || key == K_KP_ENTER || key == K_MOUSE1)
{
@ -1284,13 +1290,13 @@ void MC_Slider_Key(menuslider_t *option, int key)
if (range > option->max)
range = option->max;
option->current = range;
if (option->var)
Cvar_SetValue(option->var, range);
}
else
return;
S_LocalSound ("misc/menu2.wav");
if (option->var)
Cvar_SetValue(option->var, option->current);
}
void MC_CheckBox_Key(menucheck_t *option, menu_t *menu, int key)
@ -1370,6 +1376,7 @@ void MC_Combo_Key(menucombo_t *combo, int key)
changed:
if (combo->cvar && combo->numoptions)
Cvar_Set(combo->cvar, (char *)combo->values[combo->selectedoption]);
S_LocalSound ("misc/menu2.wav");
}
else if (key == K_LEFTARROW)
{

View File

@ -2488,18 +2488,19 @@ int captureframe;
qboolean captureframeforce;
qboolean capturepaused;
cvar_t capturerate = SCVAR("capturerate", "30");
cvar_t capturerate = CVAR("capturerate", "30");
#if defined(WINAVI)
cvar_t capturecodec = SCVAR("capturecodec", "divx");
cvar_t capturedriver = CVARD("capturedriver", "avi", "The driver to use to capture the demo. avformat can be supported via a plugin.\navi: capture directly to avi (capturecodec should be a fourcc value).\nraw: capture to a series of screenshots.");
cvar_t capturecodec = CVAR("capturecodec", "divx");
#else
cvar_t capturecodec = SCVAR("capturecodec", "tga");
cvar_t capturedriver = CVARD("capturedriver", "raw", "The driver to use to capture the demo. avformat can be supported via a plugin.\nraw: capture to a series of screenshots.");
cvar_t capturecodec = CVAR("capturecodec", "tga");
#endif
cvar_t capturesound = SCVAR("capturesound", "1");
cvar_t capturesoundchannels = SCVAR("capturesoundchannels", "1");
cvar_t capturesoundbits = SCVAR("capturesoundbits", "8");
cvar_t capturemessage = SCVAR("capturemessage", "");
cvar_t capturesound = CVAR("capturesound", "1");
cvar_t capturesoundchannels = CVAR("capturesoundchannels", "1");
cvar_t capturesoundbits = CVAR("capturesoundbits", "8");
cvar_t capturemessage = CVAR("capturemessage", "");
qboolean recordingdemo;
media_encoder_funcs_t *capturedriver[8];
media_encoder_funcs_t *currentcapture_funcs;
void *currentcapture_ctx;
@ -2509,7 +2510,9 @@ void *currentcapture_ctx;
/*screenshot capture*/
struct capture_raw_ctx
{
int frames;
char videonameprefix[MAX_QPATH];
char videonameextension[16];
vfsfile_t *audio;
};
@ -2517,6 +2520,11 @@ static void *QDECL capture_raw_begin (char *streamname, int videorate, int width
{
struct capture_raw_ctx *ctx = Z_Malloc(sizeof(*ctx));
if (!strcmp(capturecodec.string, "png") || !strcmp(capturecodec.string, "jpeg") || !strcmp(capturecodec.string, "jpg") || !strcmp(capturecodec.string, "bmp") || !strcmp(capturecodec.string, "pcx") || !strcmp(capturecodec.string, "tga"))
Q_strncpyz(ctx->videonameextension, capturecodec.string, sizeof(ctx->videonameextension));
else
Q_strncpyz(ctx->videonameextension, "tga", sizeof(ctx->videonameextension));
Q_strncpyz(ctx->videonameprefix, streamname, sizeof(ctx->videonameprefix));
ctx->audio = NULL;
if (*sndkhz)
@ -2545,7 +2553,8 @@ static void QDECL capture_raw_video (void *vctx, void *data, int frame, int widt
{
struct capture_raw_ctx *ctx = vctx;
char filename[MAX_OSPATH];
Q_snprintfz(filename, sizeof(filename), "%s/%8.8i.%s", ctx->videonameprefix, frame, capturecodec.string);
ctx->frames = frame+1;
Q_snprintfz(filename, sizeof(filename), "%s/%8.8i.%s", ctx->videonameprefix, frame, ctx->videonameextension);
SCR_ScreenShot(filename, data, width, height);
}
static void QDECL capture_raw_audio (void *vctx, void *data, int bytes)
@ -2558,10 +2567,14 @@ static void QDECL capture_raw_audio (void *vctx, void *data, int bytes)
static void QDECL capture_raw_end (void *vctx)
{
struct capture_raw_ctx *ctx = vctx;
if (ctx->audio)
VFS_CLOSE(ctx->audio);
Con_Printf("%d video frames captured\n", ctx->frames);
Z_Free(ctx);
}
static media_encoder_funcs_t capture_raw =
{
"raw",
capture_raw_begin,
capture_raw_video,
capture_raw_audio,
@ -2678,7 +2691,7 @@ static void *QDECL capture_avi_begin (char *streamname, int videorate, int width
hr = qAVIMakeCompressedStream(&ctx->compressed_video_stream, ctx->uncompressed_video_stream, &opts, NULL);
if (FAILED(hr))
{
Con_Printf("Failed to init compressor\n");
Con_Printf("AVIMakeCompressedStream failed. check codec.\n");
capture_avi_end(ctx);
return NULL;
}
@ -2688,7 +2701,7 @@ static void *QDECL capture_avi_begin (char *streamname, int videorate, int width
hr = qAVIStreamSetFormat(avi_video_stream(ctx), 0, &bitmap_info_header, sizeof(BITMAPINFOHEADER));
if (FAILED(hr))
{
Con_Printf("Failed to set format\n");
Con_Printf("AVIStreamSetFormat failed\n");
capture_avi_end(ctx);
return NULL;
}
@ -2716,6 +2729,8 @@ static void *QDECL capture_avi_begin (char *streamname, int videorate, int width
stream_header.dwRate = stream_header.dwScale * (unsigned long)ctx->wave_format.nSamplesPerSec;
stream_header.dwSampleSize = ctx->wave_format.nBlockAlign;
//FIXME: be prepared to capture audio to mp3.
hr = qAVIFileCreateStreamA(ctx->file, &ctx->uncompressed_audio_stream, &stream_header);
if (FAILED(hr))
{
@ -2748,9 +2763,8 @@ static void QDECL capture_avi_video(void *vctx, void *vdata, int frame, int widt
data[i+2] = temp;
}
//write it
Con_Printf("%i - %f\n", frame, realtime);
if (FAILED(qAVIStreamWrite(avi_video_stream(ctx), frame, 1, data, width*height * 3, ((frame%15) == 0)?AVIIF_KEYFRAME:0, NULL, NULL)))
Con_Printf("Recoring error\n");
Con_DPrintf("Recoring error\n");
}
static void QDECL capture_avi_audio(void *vctx, void *data, int bytes)
@ -2762,19 +2776,12 @@ static void QDECL capture_avi_audio(void *vctx, void *data, int bytes)
static media_encoder_funcs_t capture_avi =
{
"avi",
capture_avi_begin,
capture_avi_video,
capture_avi_audio,
capture_avi_end
};
#else
media_encoder_funcs_t capture_avi =
{
NULL,
NULL,
NULL,
NULL
};
#endif
@ -3106,28 +3113,23 @@ void Media_RecordFilm_f (void)
capturelastvideotime = realtime = 0;
captureframe = 0;
if (*fourcc)
{
if (!strcmp(fourcc, "tga") ||
!strcmp(fourcc, "png") ||
!strcmp(fourcc, "jpg") ||
!strcmp(fourcc, "pcx"))
{
currentcapture_funcs = &capture_raw;
}
else
{
currentcapture_funcs = &capture_avi;
}
}
else
{
currentcapture_funcs = &capture_avi;
}
for (i = 0; i < 8; i++)
for (i = 0; i < sizeof(pluginencodersfunc)/sizeof(pluginencodersfunc[0]); i++)
{
if (pluginencodersfunc[i])
currentcapture_funcs = pluginencodersfunc[i];
if (!strcmp(pluginencodersfunc[i]->drivername, capturedriver.string))
currentcapture_funcs = pluginencodersfunc[i];
}
//just use the first
if (!currentcapture_funcs)
{
for (i = 0; i < sizeof(pluginencodersfunc)/sizeof(pluginencodersfunc[0]); i++)
{
if (pluginencodersfunc[i])
{
currentcapture_funcs = pluginencodersfunc[i];
break;
}
}
}
if (capturesound.ival)
@ -3900,6 +3902,7 @@ void Media_Init(void)
Cvar_Register(&capturemessage, "AVI capture controls");
Cvar_Register(&capturesound, "AVI capture controls");
Cvar_Register(&capturerate, "AVI capture controls");
Cvar_Register(&capturedriver, "AVI capture controls");
Cvar_Register(&capturecodec, "AVI capture controls");
#if defined(WINAVI)

View File

@ -236,12 +236,14 @@ void M_Menu_Audio_Speakers_f (void)
menucombo_t *MC_AddCvarCombo(menu_t *menu, int x, int y, const char *caption, cvar_t *cvar, const char **ops, const char **values);
void M_Menu_Audio_f (void)
{
menu_t *menu;
extern cvar_t nosound, snd_leftisright, snd_khz, snd_speakers, ambient_level, bgmvolume, snd_playersoundvolume, ambient_fade, cl_staticsounds, snd_inactive, _snd_mixahead, snd_usemultipledevices;
int y;
menu_t *menu = M_Options_Title(&y, 0);
extern cvar_t nosound, snd_leftisright, snd_device, snd_khz, snd_speakers, ambient_level, bgmvolume, snd_playersoundvolume, ambient_fade, cl_staticsounds, snd_inactive, _snd_mixahead;
// extern cvar_t snd_noextraupdate, snd_eax, precache;
#ifdef VOICECHAT
extern cvar_t cl_voip_play, cl_voip_send;
extern cvar_t cl_voip_play, cl_voip_send, cl_voip_test, cl_voip_micamp, cl_voip_vad_threshhold, cl_voip_ducking, cl_voip_noisefilter, cl_voip_codec;
#endif
extern char **soundoutdevicecodes, **soundoutdevicenames;
static const char *soundqualityoptions[] = {
"11025 Hz",
@ -275,11 +277,43 @@ void M_Menu_Audio_f (void)
NULL
};
int y;
static const char *voipcodecoptions[] = {
"Speex (ez-compat)",
// "Raw (11025)",
"Opus (external)",
"Speex (Narrow)",
"Speex (Wide)",
NULL
};
static const char *voipcodecvalue[] = {
"0",
// "1",
"2",
"3",
"4",
NULL
};
static const char *voipsendoptions[] = {
"Push To Talk",
"Voice Activation",
"Continuous",
NULL
};
static const char *voipsendvalue[] = {
"0",
"1",
"2",
NULL
};
menubulk_t bulk[] = {
MB_REDTEXT("Sound Options", false),
MB_TEXT("\x80\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x82", false),
MB_SPACING(8),
MB_CONSOLECMD("Restart Sound", "snd_restart\n", "Restart audio systems and apply set options."),
MB_SPACING(4),
MB_COMBOCVAR("Output Device", snd_device, soundoutdevicenames, soundoutdevicecodes, NULL),
MB_SLIDER("Volume", volume, 0, 1, 0.1, NULL),
MB_COMBOCVAR("Speaker Setup", snd_speakers, speakeroptions, speakervalues, NULL),
MB_COMBOCVAR("Frequency", snd_khz, soundqualityoptions, soundqualityvalues, NULL),
@ -288,10 +322,7 @@ void M_Menu_Audio_f (void)
MB_SLIDER("Mixahead", _snd_mixahead, 0, 1, 0.05, NULL),
MB_CHECKBOXCVAR("Disable All Sounds", nosound, 0),
MB_SPACING(4),
#ifdef VOICECHAT
MB_CHECKBOXCVAR("Voice Chat", cl_voip_play, 0),
MB_CHECKBOXCVAR("Voice Activation", cl_voip_send, 0),
#endif
MB_SLIDER("Player Sound Volume", snd_playersoundvolume, 0, 1, 0.1, NULL),
MB_SLIDER("Ambient Volume", ambient_level, 0, 1, 0.1, NULL),
MB_SLIDER("Ambient Fade", ambient_fade, 0, 1000, 1, NULL),
@ -300,17 +331,28 @@ void M_Menu_Audio_f (void)
// removed music buffer
// removed precache
// removed eax2
MB_CHECKBOXCVAR("Multiple Devices", snd_usemultipledevices, 0),
// remove no extra update
MB_CHECKBOXCVAR("Sound While Inactive", snd_inactive, 0),
MB_SPACING(4),
#ifdef VOICECHAT
MB_REDTEXT("Voice Options", false),
MB_TEXT("\x80\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x82", false),
MB_SLIDER("Voice Volume", cl_voip_play, 0, 2, 0.1, NULL),
// MB_COMBOCVAR("Microphone Device", snd_micdevice, inputdeviceoptions, inputdevicevalue, NULL),
MB_CHECKBOXCVAR("Microphone Test", cl_voip_test, 0),
MB_SLIDER("Microphone Volume", cl_voip_micamp, 0, 2, 0.1, NULL),
MB_COMBOCVAR("Activation Mode", cl_voip_send, voipsendoptions, voipsendvalue, NULL),
MB_SLIDER("Act. Threshhold", cl_voip_vad_threshhold, 0, 30, 1, NULL),
MB_CHECKBOXCVAR("Audio Ducking", cl_voip_ducking, 0),
MB_CHECKBOXCVAR("Noise Cancelation", cl_voip_noisefilter, 0),
MB_COMBOCVAR("Codec", cl_voip_codec, voipcodecoptions, voipcodecvalue, NULL),
#endif
//MB_CONSOLECMD("Speaker Test", "menu_speakers\n", "Test speaker setup output."),
MB_CONSOLECMD("Restart Sound", "snd_restart\n", "Restart audio systems and apply set options."),
MB_END()
};
menu = M_Options_Title(&y, 0);
MC_AddBulk(menu, bulk, 16, 216, y);
}

View File

@ -178,6 +178,7 @@ typedef struct {
float current;
float smallchange;
float largechange;
float vx;
cvar_t *var;
const char *text;
} menuslider_t;

View File

@ -2455,6 +2455,9 @@ static void QCBUILTIN PF_cs_serverkey (pubprogfuncs_t *prinst, struct globalvars
default:
ret = "NetQuake";
break;
case CPNQ_FITZ666:
ret = "Fitz666";
break;
case CPNQ_DP5:
ret = "NetQuake DarkPlaces 5";
break;

View File

@ -2721,7 +2721,7 @@ ping time frags name
Font_BeginString(font_conchar, x+24, y, &cx, &cy); \
Font_DrawChar(cx, cy, num[2] | 0xe000 | CON_WHITEMASK); \
\
if ((cl.spectator && k == pv->cam_spec_track) ||\
if ((cl.spectator && k == Cam_TrackNum(pv)) ||\
(!cl.spectator && k == pv->playernum)) \
{ \
Font_BeginString(font_conchar, x, y, &cx, &cy); \
@ -2774,6 +2774,9 @@ void Sbar_DeathmatchOverlay (int start)
int startx, rank_width;
playerview_t *pv = r_refdef.playerview;
if (!pv)
return;
if (largegame)
skip = 8;

View File

@ -5,13 +5,9 @@ This is based on Jogi's OpenAL support.
Much of it is stripped, to try and get it clean/compliant.
Missing features:
FIXME: does not kill old sounds on replaced sound channels (quake compliance).
FIXME: no static/ambient sounds (quake compliance).
FIXME: does not support streaming audio from voice/videos (voice/q2/q3 compliance).
If the above ar implemented, it can be the default device.
FIXME: listener velocity calculations (currently ugly).
FIXME: does not track entity velocities, so no dopler (awkward, quake move playing sounds at all).
FIXME: no eax (underwater).
FIXME: does not track entity velocities, so no dopler (awkward, quake doesn't move playing sounds at all).
FIXME: no eax / efx (underwater reverb etc).
FIXME: a capture device would be useful (voice chat).
*/
@ -34,6 +30,8 @@ typedef char ALboolean;
typedef int ALsizei;
typedef void ALvoid;
static dllhandle_t *openallib;
static qboolean openallib_tried;
static AL_API ALenum (AL_APIENTRY *palGetError)( void );
static AL_API void (AL_APIENTRY *palSourcef)( ALuint sid, ALenum param, ALfloat value );
static AL_API void (AL_APIENTRY *palSourcei)( ALuint sid, ALenum param, ALint value );
@ -60,6 +58,10 @@ static AL_API void (AL_APIENTRY *palDeleteSources)( ALsizei n, const ALuint* sou
static AL_API void (AL_APIENTRY *palSpeedOfSound)( ALfloat value );
static AL_API void (AL_APIENTRY *palDistanceModel)( ALenum distanceModel );
//needed for streaming
static AL_API void (AL_APIENTRY *palGetSourcei)(ALuint source, ALenum pname, ALint *value);
static AL_API void (AL_APIENTRY *palSourceQueueBuffers)(ALuint source, ALsizei n, ALuint* buffers);
static AL_API void (AL_APIENTRY *palSourceUnqueueBuffers)(ALuint source, ALsizei n, ALuint* buffers);
#define AL_NONE 0
#define AL_FALSE 0
@ -72,9 +74,14 @@ static AL_API void (AL_APIENTRY *palDistanceModel)( ALenum distanceModel );
#define AL_BUFFER 0x1009
#define AL_GAIN 0x100A
#define AL_ORIENTATION 0x100F
#define AL_SOURCE_STATE 0x1010
#define AL_PLAYING 0x1012
#define AL_BUFFERS_PROCESSED 0x1016
#define AL_REFERENCE_DISTANCE 0x1020
#define AL_ROLLOFF_FACTOR 0x1021
#define AL_MAX_DISTANCE 0x1023
#define AL_SOURCE_TYPE 0x1027
#define AL_STREAMING 0x1029
#define AL_FORMAT_MONO8 0x1100
#define AL_FORMAT_MONO16 0x1101
#define AL_FORMAT_STEREO8 0x1102
@ -127,6 +134,7 @@ static ALC_API ALCboolean (ALC_APIENTRY *palcIsExtensionPresent)( ALCdevice
#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004
#define ALC_DEVICE_SPECIFIER 0x1005
#define ALC_EXTENSIONS 0x1006
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
//#include "AL/alut.h"
//#include "AL/al.h"
@ -134,6 +142,66 @@ static ALC_API ALCboolean (ALC_APIENTRY *palcIsExtensionPresent)( ALCdevice
//efx
#define AL_AUXILIARY_SEND_FILTER 0x20006
#define AL_FILTER_NULL 0x0000
#define AL_EFFECTSLOT_EFFECT 0x0001
#define AL_EFFECT_TYPE 0x8001
#define AL_EFFECT_REVERB 0x0001
#define AL_EFFECT_EAXREVERB 0x8000
#define AL_REVERB_DENSITY 0x0001
#define AL_REVERB_DIFFUSION 0x0002
#define AL_REVERB_GAIN 0x0003
#define AL_REVERB_GAINHF 0x0004
#define AL_REVERB_DECAY_TIME 0x0005
#define AL_REVERB_DECAY_HFRATIO 0x0006
#define AL_REVERB_REFLECTIONS_GAIN 0x0007
#define AL_REVERB_REFLECTIONS_DELAY 0x0008
#define AL_REVERB_LATE_REVERB_GAIN 0x0009
#define AL_REVERB_LATE_REVERB_DELAY 0x000A
#define AL_REVERB_AIR_ABSORPTION_GAINHF 0x000B
#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C
#define AL_REVERB_DECAY_HFLIMIT 0x000D
/* EAX Reverb effect parameters */
#define AL_EAXREVERB_DENSITY 0x0001
#define AL_EAXREVERB_DIFFUSION 0x0002
#define AL_EAXREVERB_GAIN 0x0003
#define AL_EAXREVERB_GAINHF 0x0004
#define AL_EAXREVERB_GAINLF 0x0005
#define AL_EAXREVERB_DECAY_TIME 0x0006
#define AL_EAXREVERB_DECAY_HFRATIO 0x0007
#define AL_EAXREVERB_DECAY_LFRATIO 0x0008
#define AL_EAXREVERB_REFLECTIONS_GAIN 0x0009
#define AL_EAXREVERB_REFLECTIONS_DELAY 0x000A
#define AL_EAXREVERB_REFLECTIONS_PAN 0x000B
#define AL_EAXREVERB_LATE_REVERB_GAIN 0x000C
#define AL_EAXREVERB_LATE_REVERB_DELAY 0x000D
#define AL_EAXREVERB_LATE_REVERB_PAN 0x000E
#define AL_EAXREVERB_ECHO_TIME 0x000F
#define AL_EAXREVERB_ECHO_DEPTH 0x0010
#define AL_EAXREVERB_MODULATION_TIME 0x0011
#define AL_EAXREVERB_MODULATION_DEPTH 0x0012
#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF 0x0013
#define AL_EAXREVERB_HFREFERENCE 0x0014
#define AL_EAXREVERB_LFREFERENCE 0x0015
#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR 0x0016
#define AL_EAXREVERB_DECAY_HFLIMIT 0x0017
static AL_API void*(AL_APIENTRY *palGetProcAddress)(const ALchar *fname);
static AL_API void (AL_APIENTRY *palSource3i)(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3);
static AL_API void (AL_APIENTRY *palAuxiliaryEffectSloti)(ALuint effectslot, ALenum param, ALint iValue);
static AL_API ALvoid (AL_APIENTRY *palGenAuxiliaryEffectSlots)(ALsizei n, ALuint *effectslots);
static AL_API ALvoid (AL_APIENTRY *palDeleteAuxiliaryEffectSlots)(ALsizei n, const ALuint *effectslots);
static AL_API ALvoid (AL_APIENTRY *palDeleteEffects)(ALsizei n, const ALuint *effects);
static AL_API ALvoid (AL_APIENTRY *palGenEffects)(ALsizei n, ALuint *effects);
static AL_API ALvoid (AL_APIENTRY *palEffecti)(ALuint effect, ALenum param, ALint iValue);
static AL_API ALvoid (AL_APIENTRY *palEffectiv)(ALuint effect, ALenum param, const ALint *piValues);
static AL_API ALvoid (AL_APIENTRY *palEffectf)(ALuint effect, ALenum param, ALfloat flValue);
static AL_API ALvoid (AL_APIENTRY *palEffectfv)(ALuint effect, ALenum param, const ALfloat *pflValues);
#define SOUNDVARS "OpenAL variables"
@ -155,30 +223,35 @@ static void S_Info(void);
static void S_Shutdown_f(void);
*/
static cvar_t s_al_enable = CVAR("s_al_enable", "0");
static cvar_t s_al_debug = CVAR("s_al_debug", "0");
static cvar_t s_al_max_distance = CVARFC("s_al_max_distance", "1000",0,OnChangeALMaxDistance);
static cvar_t s_al_speedofsound = CVARFC("s_al_speedofsound", "343.3",0,OnChangeALSpeedOfSound);
static cvar_t s_al_dopplerfactor = CVARFC("s_al_dopplerfactor", "3.0",0,OnChangeALDopplerFactor);
static cvar_t s_al_distancemodel = CVARFC("s_al_distancemodel", "1",0,OnChangeALDistanceModel);
static cvar_t s_al_distancemodel = CVARFC("s_al_distancemodel", "2",0,OnChangeALDistanceModel);
static cvar_t s_al_rolloff_factor = CVAR("s_al_rolloff_factor", "1");
static cvar_t s_al_reference_distance = CVAR("s_al_reference_distance", "120");static cvar_t s_al_velocityscale = CVAR("s_al_velocityscale", "1");
static cvar_t s_al_static_listener = CVAR("s_al_static_listener", "0"); //cheat
#define NUM_SOURCES MAX_CHANNELS
static ALuint source[NUM_SOURCES];
typedef struct
{
#define NUM_SOURCES MAX_CHANNELS
ALuint source[NUM_SOURCES];
static ALCdevice *OpenAL_Device;
static ALCcontext *OpenAL_Context;
ALCdevice *OpenAL_Device;
ALCcontext *OpenAL_Context;
static ALfloat ListenPos[] = { 0.0, 0.0, 0.0 };
ALfloat ListenPos[3];// = { 0.0, 0.0, 0.0 };
// Velocity of the listener.
static ALfloat ListenVel[] = { 0.0, 0.0, 0.0 };
// Velocity of the listener.
ALfloat ListenVel[3];// = { 0.0, 0.0, 0.0 };
// Orientation of the listener. (first 3 elements are "at", second 3 are "up")
static ALfloat ListenOri[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 };
// Orientation of the listener. (first 3 elements are "at", second 3 are "up")
ALfloat ListenOri[6];// = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 };
int cureffect;
ALuint effectslot; //the global reverb slot
ALuint effecttype[2]; //effect used when underwater
} oalinfo_t;
static void PrintALError(char *string)
{
ALenum err;
@ -212,7 +285,7 @@ static void PrintALError(char *string)
Con_Printf("OpenAL - %s: %x: %s\n",string,err,text);
}
void OpenAL_LoadCache(sfx_t *s, sfxcache_t *sc)
void OpenAL_LoadCache(unsigned int *bufptr, sfxcache_t *sc)
{
unsigned int fmt;
unsigned int size;
@ -246,7 +319,7 @@ void OpenAL_LoadCache(sfx_t *s, sfxcache_t *sc)
return;
}
PrintALError("pre Buffer Data");
palGenBuffers(1, &s->openal_buffer);
palGenBuffers(1, bufptr);
/*openal is inconsistant and supports only 8bit unsigned or 16bit signed*/
if (sc->width == 1)
{
@ -257,11 +330,11 @@ void OpenAL_LoadCache(sfx_t *s, sfxcache_t *sc)
{
tmp[i] = src[i]+128;
}
palBufferData(s->openal_buffer, fmt, tmp, size, sc->speed);
palBufferData(*bufptr, fmt, tmp, size, sc->speed);
free(tmp);
}
else
palBufferData(s->openal_buffer, fmt, sc->data, size, sc->speed);
palBufferData(*bufptr, fmt, sc->data, size, sc->speed);
//FIXME: we need to handle oal-oom error codes
@ -270,7 +343,6 @@ void OpenAL_LoadCache(sfx_t *s, sfxcache_t *sc)
void OpenAL_CvarInit(void)
{
Cvar_Register(&s_al_enable, SOUNDVARS);
Cvar_Register(&s_al_debug, SOUNDVARS);
Cvar_Register(&s_al_max_distance, SOUNDVARS);
Cvar_Register(&s_al_dopplerfactor, SOUNDVARS);
@ -283,111 +355,58 @@ void OpenAL_CvarInit(void)
}
extern float voicevolumemod;
void OpenAL_Update_Listener(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up, vec3_t velocity)
static void OpenAL_ListenerUpdate(soundcardinfo_t *sc, vec3_t origin, vec3_t forward, vec3_t right, vec3_t up, vec3_t velocity)
{
VectorScale(velocity, s_al_velocityscale.value, ListenVel);
VectorCopy(origin, ListenPos);
oalinfo_t *oali = sc->handle;
ListenOri[0] = forward[0];
ListenOri[1] = forward[1];
ListenOri[2] = forward[2];
ListenOri[3] = up[0];
ListenOri[4] = up[1];
ListenOri[5] = up[2];
VectorScale(velocity, s_al_velocityscale.value, oali->ListenVel);
VectorCopy(origin, oali->ListenPos);
oali->ListenOri[0] = forward[0];
oali->ListenOri[1] = forward[1];
oali->ListenOri[2] = forward[2];
oali->ListenOri[3] = up[0];
oali->ListenOri[4] = up[1];
oali->ListenOri[5] = up[2];
if (!s_al_static_listener.value)
{
palListenerf(AL_GAIN, volume.value*voicevolumemod);
palListenerfv(AL_POSITION, ListenPos);
palListenerfv(AL_VELOCITY, ListenVel);
palListenerfv(AL_ORIENTATION, ListenOri);
palListenerfv(AL_POSITION, oali->ListenPos);
palListenerfv(AL_VELOCITY, oali->ListenVel);
palListenerfv(AL_ORIENTATION, oali->ListenOri);
}
}
/*
static void OpenAL_StopAllSounds(qboolean clear)
{
Con_Printf("-------------------------- %i ---------------\n",clear);
palSourceStopv(NUM_SOURCES,source);
palSourceStopv(NUM_SOURCES,static_source);
num_sfx=0;
num_static_source=0;
if (clear)
{
}
}
*/
/*
void OpenAL_StartSound(int entnum, int entchannel, sfx_t * sfx, vec3_t origin, float fvol, float attenuation, float pitch)
{
vec3_t tmp;
extern cvar_t temp1;
if (!temp1.value)
temp1.value = 1;
if (!sfx->openal_buffer)
{
sfxcache_t *sc = Cache_Check(&sfx->cache);
if (!sc)
return;
OpenAL_LoadCache(sfx, sc);
}
if (!origin)
VectorClear(tmp);
else
{
tmp[0] = origin[0];
tmp[1] = origin[1];
tmp[2] = origin[2];
}
PrintALError("pre start sound");
palSourceStop(source[num_sfx]);
palSourcei(source[num_sfx], AL_BUFFER, sfx->openal_buffer);
palSourcef(source[num_sfx], AL_PITCH, pitch*temp1.value);
palSourcef(source[num_sfx], AL_GAIN, fvol);
// palSourcef(source[num_sfx], AL_MAX_DISTANCE, s_al_max_distance.value);
// palSourcef(source[num_sfx], AL_ROLLOFF_FACTOR, s_al_rolloff_factor.value);
palSourcefv(source[num_sfx], AL_POSITION, tmp);
palSourcefv(source[num_sfx], AL_VELOCITY, vec3_origin);
palSourcef(source[num_sfx], AL_REFERENCE_DISTANCE, s_al_reference_distance.value);
if (entnum == -1 || entnum == cl.playernum[0]+1)
{
palSourcei(source[num_sfx], AL_SOURCE_RELATIVE, AL_TRUE);
palSourcef(source[num_sfx], AL_ROLLOFF_FACTOR, 0.0f);
}
else
{
palSourcei(source[num_sfx], AL_SOURCE_RELATIVE, AL_FALSE);
palSourcef(source[num_sfx], AL_ROLLOFF_FACTOR, s_al_rolloff_factor.value);
}
palSourcePlay(source[num_sfx]);
num_sfx++;
if (num_sfx >= NUM_SOURCES)
num_sfx =0;
PrintALError("post start sound");
}*/
static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned int schanged)
{
oalinfo_t *oali = sc->handle;
ALuint src;
sfx_t *sfx = chan->sfx;
float pitch;
int chnum = chan - sc->channel;
ALuint buf;
src = source[chan - sc->channel];
if (chnum >= NUM_SOURCES)
return;
src = oali->source[chnum];
if (!src)
{
//not currently playing. be prepared to create one
if (!sfx || chan->master_vol == 0)
return;
palGenSources(1, &src);
source[chan - sc->channel] = src;
schanged = true;
//unable to start a new sound source, give up.
if (!src)
{
//FIXME: find one which has already stopped and steal it.
Con_Printf("Out of OpenAL sources!\n");
return;
}
oali->source[chnum] = src;
schanged = true; //should normally be true anyway, but hey
}
PrintALError("pre start sound");
@ -395,33 +414,75 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned
if (schanged && src)
palSourceStop(src);
//reclaim any queued buffers
palGetSourcei(src, AL_SOURCE_TYPE, &buf);
if (buf == AL_STREAMING)
{
for(;;)
{
palGetSourcei(src, AL_BUFFERS_PROCESSED, &buf);
if (!buf)
break;
palSourceUnqueueBuffers(src, 1, &buf);
palDeleteBuffers(1, &buf);
}
}
/*just wanted to stop it?*/
if (!sfx || chan->master_vol == 0)
{
if (src)
{
palDeleteBuffers(1, &src);
source[chan - sc->channel] = 0;
palDeleteSources(1, &src);
oali->source[chnum] = 0;
}
return;
}
if (schanged)
if (schanged || sfx->decoder.decodedata)
{
if (!sfx->openal_buffer)
{
sfxcache_t *sc = S_LoadSound(sfx);
if (!sc) /*ack! can't start it if its not loaded!*/
return;
OpenAL_LoadCache(sfx, sc);
}
if (!S_LoadSound(sfx))
return; //can't load it
if (sfx->decoder.decodedata)
{
int offset;
sfxcache_t sbuf, *sc = sfx->decoder.decodedata(sfx, &sbuf, chan->pos>>PITCHSHIFT, 65536);
memcpy(&sbuf, sc, sizeof(sbuf));
palSourcei(src, AL_BUFFER, sfx->openal_buffer);
//hack up the sound to offset it correctly
offset = (chan->pos>>PITCHSHIFT) - sbuf.soundoffset;
sbuf.data += offset * sc->width*sc->numchannels;
sbuf.length -= offset;
sbuf.soundoffset = 0;
//build a buffer with it and queue it up.
//buffer will be purged later on when its unqueued
OpenAL_LoadCache(&buf, &sbuf);
palSourceQueueBuffers(src, 1, &buf);
//yay
chan->pos += sbuf.length<<PITCHSHIFT;
palGetSourcei(src, AL_SOURCE_STATE, &buf);
if (buf != AL_PLAYING)
schanged = true;
}
else
{
OpenAL_LoadCache(&sfx->openal_buffer, sfx->decoder.buf);
palSourcei(src, AL_BUFFER, sfx->openal_buffer);
}
}
else
palSourcei(src, AL_BUFFER, sfx->openal_buffer);
}
palSourcef(src, AL_GAIN, chan->master_vol/255.0f);
// palSourcef(src, AL_MAX_DISTANCE, s_al_max_distance.value);
// palSourcef(src, AL_ROLLOFF_FACTOR, s_al_rolloff_factor.value);
palSourcefv(src, AL_POSITION, chan->origin);
if (chan->entnum == -1 || chan->entnum == cl.playerview[0].viewentity)
palSourcefv(src, AL_POSITION, vec3_origin);
else
palSourcefv(src, AL_POSITION, chan->origin);
palSourcefv(src, AL_VELOCITY, vec3_origin);
if (schanged)
@ -429,17 +490,34 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned
pitch = (float)chan->rate/(1<<PITCHSHIFT);
palSourcef(src, AL_PITCH, pitch);
palSourcef(src, AL_REFERENCE_DISTANCE, s_al_reference_distance.value);
if (chan->entnum == -2) //don't do the underwater thing on static sounds. it sounds like arse with all those sources.
palSource3i(src, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL);
else
palSource3i(src, AL_AUXILIARY_SEND_FILTER, oali->effectslot, 0, AL_FILTER_NULL);
palSourcei(src, AL_LOOPING, chan->looping?AL_TRUE:AL_FALSE);
if (chan->entnum == -1 || chan->entnum == cl.playernum[0]+1)
if (chan->entnum == -1 || chan->entnum == cl.playerview[0].viewentity)
{
palSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE);
palSourcef(src, AL_ROLLOFF_FACTOR, 0.0f);
// palSourcef(src, AL_ROLLOFF_FACTOR, 0.0f);
}
else
{
palSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE);
palSourcef(src, AL_ROLLOFF_FACTOR, s_al_rolloff_factor.value*chan->dist_mult);
// palSourcef(src, AL_ROLLOFF_FACTOR, s_al_rolloff_factor.value*chan->dist_mult);
}
switch(s_al_distancemodel.ival)
{
default:
palSourcef(src, AL_ROLLOFF_FACTOR, s_al_reference_distance.value);
palSourcef(src, AL_REFERENCE_DISTANCE, 1);
palSourcef(src, AL_MAX_DISTANCE, 1/chan->dist_mult); //clamp to the maximum distance you'd normally be allowed to hear... this is probably going to be annoying.
break;
case 2: //linear, mimic quake.
palSourcef(src, AL_ROLLOFF_FACTOR, 1);
palSourcef(src, AL_REFERENCE_DISTANCE, 0);
palSourcef(src, AL_MAX_DISTANCE, 1/chan->dist_mult);
break;
}
/*and start it up again*/
@ -468,9 +546,9 @@ static void S_Info (void)
}
*/
static qboolean OpenAL_Init(void)
static qboolean OpenAL_InitLibrary(void)
{
dllfunction_t openalfuncs[] =
static dllfunction_t openalfuncs[] =
{
{(void*)&palGetError, "alGetError"},
{(void*)&palSourcef, "alSourcef"},
@ -493,6 +571,11 @@ static qboolean OpenAL_Init(void)
{(void*)&palSpeedOfSound, "alSpeedOfSound"},
{(void*)&palDistanceModel, "alDistanceModel"},
{(void*)&palGetProcAddress, "alGetProcAddress"},
{(void*)&palGetSourcei, "alGetSourcei"},
{(void*)&palSourceQueueBuffers, "alSourceQueueBuffers"},
{(void*)&palSourceUnqueueBuffers, "alSourceUnqueueBuffers"},
{(void*)&palcOpenDevice, "alcOpenDevice"},
{(void*)&palcCloseDevice, "alcCloseDevice"},
{(void*)&palcCreateContext, "alcCreateContext"},
@ -503,33 +586,56 @@ static qboolean OpenAL_Init(void)
{(void*)&palcIsExtensionPresent, "alcIsExtensionPresent"},
{NULL}
};
if (!Sys_LoadLibrary("OpenAL32", openalfuncs))
if (!openallib_tried)
{
openallib_tried = true;
openallib = Sys_LoadLibrary("OpenAL32", openalfuncs);
}
return !!openallib;
}
static qboolean OpenAL_Init(soundcardinfo_t *sc, const char *devname)
{
oalinfo_t *oali = Z_Malloc(sizeof(oalinfo_t));
sc->handle = oali;
if (!OpenAL_InitLibrary())
{
Con_Printf("OpenAL is not installed\n");
return false;
}
OpenAL_Device = palcOpenDevice(NULL);
if (OpenAL_Device == NULL)
if (oali->OpenAL_Context)
{
Con_Printf("OpenAL: only able to load one device at a time\n");
return false;
}
oali->OpenAL_Device = palcOpenDevice(devname);
if (oali->OpenAL_Device == NULL)
{
PrintALError("Could not init a sound device\n");
return false;
}
OpenAL_Context = palcCreateContext(OpenAL_Device, NULL);
palcMakeContextCurrent(OpenAL_Context);
// palcProcessContext(OpenAL_Context);
oali->OpenAL_Context = palcCreateContext(oali->OpenAL_Device, NULL);
if (!oali->OpenAL_Context)
return false;
palcMakeContextCurrent(oali->OpenAL_Context);
// palcProcessContext(oali->OpenAL_Context);
//S_Info();
palGenSources(NUM_SOURCES, source);
//fixme...
memset(oali->source, 0, sizeof(oali->source));
PrintALError("alGensources for normal sources");
palListenerfv(AL_POSITION, ListenPos);
palListenerfv(AL_VELOCITY, ListenVel);
palListenerfv(AL_ORIENTATION, ListenOri);
palListenerfv(AL_POSITION, oali->ListenPos);
palListenerfv(AL_VELOCITY, oali->ListenVel);
palListenerfv(AL_ORIENTATION, oali->ListenOri);
return true;
}
@ -595,6 +701,17 @@ static void OpenAL_UnlockBuffer (soundcardinfo_t *sc, void *buffer)
static void OpenAL_SetUnderWater (soundcardinfo_t *sc, qboolean underwater)
{
oalinfo_t *oali = sc->handle;
if (!oali->effectslot)
return;
//don't spam it
if (oali->cureffect == underwater)
return;
oali->cureffect = underwater;
PrintALError("preunderwater");
palAuxiliaryEffectSloti(oali->effectslot, AL_EFFECTSLOT_EFFECT, oali->effecttype[oali->cureffect]);
PrintALError("postunderwater");
//Con_Printf("OpenAL: SetUnderWater %i\n", underwater);
}
@ -613,9 +730,10 @@ static unsigned int OpenAL_GetDMAPos (soundcardinfo_t *sc)
static void OpenAL_Shutdown (soundcardinfo_t *sc)
{
oalinfo_t *oali = sc->handle;
int i;
palDeleteSources(NUM_SOURCES, source);
palDeleteSources(NUM_SOURCES, oali->source);
/*make sure the buffers are cleared from the sound effects*/
for (i=0;i<num_sfx;i++)
@ -627,28 +745,121 @@ static void OpenAL_Shutdown (soundcardinfo_t *sc)
}
}
palcDestroyContext(OpenAL_Context);
OpenAL_Context = NULL;
palcCloseDevice(OpenAL_Device);
OpenAL_Device = NULL;
palDeleteAuxiliaryEffectSlots(1, &oali->effectslot);
palDeleteEffects(1, &oali->effecttype[1]);
palcDestroyContext(oali->OpenAL_Context);
palcCloseDevice(oali->OpenAL_Device);
Z_Free(oali);
}
static int OpenAL_InitCard(soundcardinfo_t *sc, int cardnum)
typedef struct {
float flDensity;
float flDiffusion;
float flGain;
float flGainHF;
float flGainLF;
float flDecayTime;
float flDecayHFRatio;
float flDecayLFRatio;
float flReflectionsGain;
float flReflectionsDelay;
float flReflectionsPan[3];
float flLateReverbGain;
float flLateReverbDelay;
float flLateReverbPan[3];
float flEchoTime;
float flEchoDepth;
float flModulationTime;
float flModulationDepth;
float flAirAbsorptionGainHF;
float flHFReference;
float flLFReference;
float flRoomRolloffFactor;
int iDecayHFLimit;
} EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES;
#define EFX_REVERB_PRESET_PSYCHOTIC \
{ 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
#define EFX_REVERB_PRESET_UNDERWATER \
{ 0.3645f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 1.4900f, 0.1000f, 1.0000f, 0.5963f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 7.0795f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 1.1800f, 0.3480f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
ALuint OpenAL_LoadEffect(const EFXEAXREVERBPROPERTIES *reverb)
{
if (cardnum != 0)
return 2;
ALuint effect;
palGenEffects(1, &effect);
if(1)//alGetEnumValue("AL_EFFECT_EAXREVERB") != 0)
{
/* EAX Reverb is available. Set the EAX effect type then load the
* reverb properties. */
palEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
if (!s_al_enable.ival)
return 2;
palEffectf(effect, AL_EAXREVERB_DENSITY, reverb->flDensity);
palEffectf(effect, AL_EAXREVERB_DIFFUSION, reverb->flDiffusion);
palEffectf(effect, AL_EAXREVERB_GAIN, reverb->flGain);
palEffectf(effect, AL_EAXREVERB_GAINHF, reverb->flGainHF);
palEffectf(effect, AL_EAXREVERB_GAINLF, reverb->flGainLF);
palEffectf(effect, AL_EAXREVERB_DECAY_TIME, reverb->flDecayTime);
palEffectf(effect, AL_EAXREVERB_DECAY_HFRATIO, reverb->flDecayHFRatio);
palEffectf(effect, AL_EAXREVERB_DECAY_LFRATIO, reverb->flDecayLFRatio);
palEffectf(effect, AL_EAXREVERB_REFLECTIONS_GAIN, reverb->flReflectionsGain);
palEffectf(effect, AL_EAXREVERB_REFLECTIONS_DELAY, reverb->flReflectionsDelay);
palEffectfv(effect, AL_EAXREVERB_REFLECTIONS_PAN, reverb->flReflectionsPan);
palEffectf(effect, AL_EAXREVERB_LATE_REVERB_GAIN, reverb->flLateReverbGain);
palEffectf(effect, AL_EAXREVERB_LATE_REVERB_DELAY, reverb->flLateReverbDelay);
palEffectfv(effect, AL_EAXREVERB_LATE_REVERB_PAN, reverb->flLateReverbPan);
palEffectf(effect, AL_EAXREVERB_ECHO_TIME, reverb->flEchoTime);
palEffectf(effect, AL_EAXREVERB_ECHO_DEPTH, reverb->flEchoDepth);
palEffectf(effect, AL_EAXREVERB_MODULATION_TIME, reverb->flModulationTime);
palEffectf(effect, AL_EAXREVERB_MODULATION_DEPTH, reverb->flModulationDepth);
palEffectf(effect, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, reverb->flAirAbsorptionGainHF);
palEffectf(effect, AL_EAXREVERB_HFREFERENCE, reverb->flHFReference);
palEffectf(effect, AL_EAXREVERB_LFREFERENCE, reverb->flLFReference);
palEffectf(effect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, reverb->flRoomRolloffFactor);
palEffecti(effect, AL_EAXREVERB_DECAY_HFLIMIT, reverb->iDecayHFLimit);
}
else
{
/* No EAX Reverb. Set the standard reverb effect type then load the
* available reverb properties. */
palEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
Con_Printf("Initiating OpenAL sound device.\n");
palEffectf(effect, AL_REVERB_DENSITY, reverb->flDensity);
palEffectf(effect, AL_REVERB_DIFFUSION, reverb->flDiffusion);
palEffectf(effect, AL_REVERB_GAIN, reverb->flGain);
palEffectf(effect, AL_REVERB_GAINHF, reverb->flGainHF);
palEffectf(effect, AL_REVERB_DECAY_TIME, reverb->flDecayTime);
palEffectf(effect, AL_REVERB_DECAY_HFRATIO, reverb->flDecayHFRatio);
palEffectf(effect, AL_REVERB_REFLECTIONS_GAIN, reverb->flReflectionsGain);
palEffectf(effect, AL_REVERB_REFLECTIONS_DELAY, reverb->flReflectionsDelay);
palEffectf(effect, AL_REVERB_LATE_REVERB_GAIN, reverb->flLateReverbGain);
palEffectf(effect, AL_REVERB_LATE_REVERB_DELAY, reverb->flLateReverbDelay);
palEffectf(effect, AL_REVERB_AIR_ABSORPTION_GAINHF, reverb->flAirAbsorptionGainHF);
palEffectf(effect, AL_REVERB_ROOM_ROLLOFF_FACTOR, reverb->flRoomRolloffFactor);
palEffecti(effect, AL_REVERB_DECAY_HFLIMIT, reverb->iDecayHFLimit);
}
return effect;
}
if (OpenAL_Init() == false)
static qboolean QDECL OpenAL_InitCard(soundcardinfo_t *sc, const char *devname)
{
oalinfo_t *oali;
//no default support, because we're buggy as fuck
if (!devname)
return false;
if (!devname || !*devname)
devname = palcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
Con_Printf("Initiating OpenAL: %s.\n", devname);
if (OpenAL_Init(sc, devname) == false)
{
Con_Printf(CON_ERROR "OpenAL init failed\n");
return false;
}
oali = sc->handle;
Con_DPrintf("OpenAL AL Extension : %s\n",palGetString(AL_EXTENSIONS));
Con_DPrintf("OpenAL ALC Extension : %s\n",palcGetString(oali->OpenAL_Device,ALC_EXTENSIONS));
sc->Lock = OpenAL_LockBuffer;
sc->Unlock = OpenAL_UnlockBuffer;
@ -657,10 +868,10 @@ static int OpenAL_InitCard(soundcardinfo_t *sc, int cardnum)
sc->Shutdown = OpenAL_Shutdown;
sc->GetDMAPos = OpenAL_GetDMAPos;
sc->ChannelUpdate = OpenAL_ChannelUpdate;
sc->ListenerUpdate = OpenAL_ListenerUpdate;
Q_snprintfz(sc->name, sizeof(sc->name), "OpenAL device");
Q_snprintfz(sc->name, sizeof(sc->name), "%s", devname);
sc->openal = 1;
sc->inactive_sound = true;
sc->selfpainting = true;
@ -668,9 +879,53 @@ static int OpenAL_InitCard(soundcardinfo_t *sc, int cardnum)
Cvar_ForceCallback(&s_al_speedofsound);
Cvar_ForceCallback(&s_al_dopplerfactor);
Cvar_ForceCallback(&s_al_max_distance);
PrintALError("preeffects");
palSource3i = palGetProcAddress("alSource3i");
palAuxiliaryEffectSloti = palGetProcAddress("alAuxiliaryEffectSloti");
palGenAuxiliaryEffectSlots = palGetProcAddress("alGenAuxiliaryEffectSlots");
palDeleteAuxiliaryEffectSlots = palGetProcAddress("alDeleteAuxiliaryEffectSlots");
palDeleteEffects = palGetProcAddress("alDeleteEffects");
palGenEffects = palGetProcAddress("alGenEffects");
palEffecti = palGetProcAddress("alEffecti");
palEffectiv = palGetProcAddress("alEffectiv");
palEffectf = palGetProcAddress("alEffectf");
palEffectfv = palGetProcAddress("alEffectfv");
palGenAuxiliaryEffectSlots(1, &oali->effectslot);
oali->cureffect = 0;
oali->effecttype[0] = 0;
{
EFXEAXREVERBPROPERTIES uw = EFX_REVERB_PRESET_UNDERWATER;
oali->effecttype[1] = OpenAL_LoadEffect(&uw);
}
PrintALError("posteffects");
return true;
}
int (*pOPENAL_InitCard) (soundcardinfo_t *sc, int cardnum) = &OpenAL_InitCard;
static qboolean QDECL OpenAL_Enumerate(void (QDECL *callback)(const char *driver, const char *devicecode, const char *readabledevice))
{
const char *devnames;
if (!OpenAL_InitLibrary())
return true; //enumerate nothing if al is disabled
devnames = palcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
if (!devnames)
devnames = palcGetString(NULL, ALC_DEVICE_SPECIFIER);
while(*devnames)
{
callback("OpenAL", devnames, va("OAL:%s", devnames));
devnames += strlen(devnames)+1;
}
return true;
}
sounddriver_t OPENAL_Output =
{
"OpenAL",
OpenAL_InitCard,
OpenAL_Enumerate
};
#endif

View File

@ -36,10 +36,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
FORCE_DEFINE_GUID(IID_IKsPropertySet, 0x31efac30, 0x515c, 0x11d0, 0xa9, 0xaa, 0x00, 0xaa, 0x00, 0x61, 0xbe, 0x93);
#endif
#define SND_ERROR 0
#define SND_LOADED 1
#define SND_NOMORE 2 //like error, but doesn't try the next card.
#ifdef AVAIL_DSOUND
#define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c)
@ -86,7 +82,7 @@ static void DSOUND_Restore(soundcardinfo_t *sc)
dh->pDSBuf->lpVtbl->Play(dh->pDSBuf, 0, 0, DSBPLAY_LOOPING);
}
DWORD dwSize;
static DWORD dsound_locksize;
static void *DSOUND_Lock(soundcardinfo_t *sc, unsigned int *sampidx)
{
void *ret;
@ -96,11 +92,11 @@ static void *DSOUND_Lock(soundcardinfo_t *sc, unsigned int *sampidx)
HRESULT hresult;
dshandle_t *dh = sc->handle;
dwSize=0;
dsound_locksize=0;
reps = 0;
while ((hresult = dh->pDSBuf->lpVtbl->Lock(dh->pDSBuf, 0, dh->gSndBufSize, (void**)&ret, &dwSize,
while ((hresult = dh->pDSBuf->lpVtbl->Lock(dh->pDSBuf, 0, dh->gSndBufSize, (void**)&ret, &dsound_locksize,
(void**)&pbuf2, &dwSize2, 0)) != DS_OK)
{
if (hresult != DSERR_BUFFERLOST)
@ -125,7 +121,7 @@ static void *DSOUND_Lock(soundcardinfo_t *sc, unsigned int *sampidx)
static void DSOUND_Unlock(soundcardinfo_t *sc, void *buffer)
{
dshandle_t *dh = sc->handle;
dh->pDSBuf->lpVtbl->Unlock(dh->pDSBuf, buffer, dwSize, NULL, 0);
dh->pDSBuf->lpVtbl->Unlock(dh->pDSBuf, buffer, dsound_locksize, NULL, 0);
}
/*
@ -190,24 +186,6 @@ static void DSOUND_Shutdown (soundcardinfo_t *sc)
DSOUND_Shutdown_Internal(sc);
}
GUID FAR *dsndguid;
int dsnd_guids;
static BOOL (CALLBACK DSEnumCallback)(GUID FAR *guid, LPCSTR str1, LPCSTR str2, LPVOID parm)
{
soundcardinfo_t *sc = parm;
if (guid == NULL)
return TRUE;
if (sc->audio_fd == dsnd_guids)
{
Q_strncpyz(sc->name, str1, sizeof(sc->name));
dsndguid = guid;
}
dsnd_guids++;
return TRUE;
}
/*
Direct Sound.
These following defs should be moved to winquake.h somewhere.
@ -530,6 +508,30 @@ static void DSOUND_Submit(soundcardinfo_t *sc, int start, int end)
{
}
static qboolean DSOUND_InitOutputLibrary(void)
{
if (!hInstDS)
{
hInstDS = LoadLibrary("dsound.dll");
if (hInstDS == NULL)
{
Con_SafePrintf ("Couldn't load dsound.dll\n");
return false;
}
pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate");
if (!pDirectSoundCreate)
{
Con_SafePrintf ("Couldn't get DS proc addr\n");
return false;
}
pDirectSoundEnumerate = (void *)GetProcAddress(hInstDS,"DirectSoundEnumerateA");
}
return true;
}
/*
==================
SNDDMA_InitDirect
@ -537,7 +539,7 @@ SNDDMA_InitDirect
Direct-Sound support
==================
*/
static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, char *cardname)
{
extern cvar_t snd_inactive;
#if _MSC_VER > 1200 //fixme err
@ -555,9 +557,24 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
qboolean primary_format_set;
dshandle_t *dh;
char *buffer;
GUID guid, *dsguid;
memset (&format, 0, sizeof(format));
if (*sc->name)
{
wchar_t mssuck[128];
mbstowcs(mssuck, sc->name, sizeof(mssuck)/sizeof(mssuck[0])-1);
CLSIDFromString(mssuck, &guid);
dsguid = &guid;
}
else
{
memset(&guid, 0, sizeof(GUID));
dsguid = NULL;
}
if (sc->sn.numchannels >= 8) // 7.1 surround
{
format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
@ -606,35 +623,8 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
format.Format.nAvgBytesPerSec = format.Format.nSamplesPerSec
*format.Format.nBlockAlign;
if (!hInstDS)
{
hInstDS = LoadLibrary("dsound.dll");
if (hInstDS == NULL)
{
Con_SafePrintf ("Couldn't load dsound.dll\n");
return SND_ERROR;
}
pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate");
if (!pDirectSoundCreate)
{
Con_SafePrintf ("Couldn't get DS proc addr\n");
return SND_ERROR;
}
pDirectSoundEnumerate = (void *)GetProcAddress(hInstDS,"DirectSoundEnumerateA");
}
dsnd_guids=0;
dsndguid=NULL;
if (pDirectSoundEnumerate)
pDirectSoundEnumerate(&DSEnumCallback, sc);
if (!snd_usemultipledevices.ival) //if only one device, ALWAYS use the default.
dsndguid=NULL;
else if (!dsndguid) //no more...
return SND_NOMORE;
if (!DSOUND_InitOutputLibrary())
return false;
sc->handle = Z_Malloc(sizeof(dshandle_t));
dh = sc->handle;
@ -648,19 +638,21 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
if (FAILED(CoCreateInstance( &CLSID_EAXDirectSound, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound, (void **)&dh->pDS )))
dh->pDS=NULL;
else
IDirectSound_Initialize(dh->pDS, dsndguid);
{
IDirectSound_Initialize(dh->pDS, dsguid);
}
}
if (!dh->pDS)
#endif
#endif
{
while ((hresult = iDirectSoundCreate(dsndguid, &dh->pDS, NULL)) != DS_OK)
while ((hresult = iDirectSoundCreate(dsguid, &dh->pDS, NULL)) != DS_OK)
{
if (hresult != DSERR_ALLOCATED)
{
Con_SafePrintf (": create failed\n");
return SND_ERROR;
return false;
}
// if (MessageBox (NULL,
@ -672,11 +664,21 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
Con_SafePrintf (": failure\n"
" hardware already in use\n"
" Close the other app then use snd_restart\n");
return SND_ERROR;
return false;
// }
}
}
#ifdef _SDL
#define mainwindow GetDesktopWindow()
#endif
if (DS_OK != dh->pDS->lpVtbl->SetCooperativeLevel (dh->pDS, mainwindow, DSSCL_EXCLUSIVE))
{
Con_SafePrintf ("Set coop level failed\n");
DSOUND_Shutdown_Internal (sc);
return false;
}
dscaps.dwSize = sizeof(dscaps);
if (DS_OK != dh->pDS->lpVtbl->GetCaps (dh->pDS, &dscaps))
@ -688,17 +690,7 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
{
Con_SafePrintf ("No DirectSound driver installed\n");
DSOUND_Shutdown_Internal (sc);
return SND_ERROR;
}
#ifdef _SDL
#define mainwindow GetDesktopWindow()
#endif
if (DS_OK != dh->pDS->lpVtbl->SetCooperativeLevel (dh->pDS, mainwindow, DSSCL_EXCLUSIVE))
{
Con_SafePrintf ("Set coop level failed\n");
DSOUND_Shutdown_Internal (sc);
return SND_ERROR;
return false;
}
@ -776,7 +768,7 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
{
Con_SafePrintf ("DS:CreateSoundBuffer Failed");
DSOUND_Shutdown_Internal (sc);
return SND_ERROR;
return false;
}
sc->sn.numchannels = format.Format.nChannels;
@ -787,7 +779,7 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
{
Con_SafePrintf ("DS:GetCaps failed\n");
DSOUND_Shutdown_Internal (sc);
return SND_ERROR;
return false;
}
// if (snd_firsttime)
@ -799,14 +791,14 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
{
Con_SafePrintf ("Set coop level failed\n");
DSOUND_Shutdown_Internal (sc);
return SND_ERROR;
return false;
}
if (DS_OK != dh->pDSPBuf->lpVtbl->GetCaps (dh->pDSPBuf, &dsbcaps))
{
Con_Printf ("DS:GetCaps failed\n");
DSOUND_Shutdown_Internal (sc);
return SND_ERROR;
return false;
}
dh->pDSBuf = dh->pDSPBuf;
@ -835,14 +827,14 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
{
Con_SafePrintf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n");
DSOUND_Shutdown_Internal (sc);
return SND_ERROR;
return false;
}
if (++reps > 10000)
{
Con_SafePrintf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n");
DSOUND_Shutdown_Internal (sc);
return SND_ERROR;
return false;
}
}
@ -889,7 +881,7 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
IKsPropertySet_Release(dh->EaxKsPropertiesSet);
dh->EaxKsPropertiesSet = NULL;
Con_SafePrintf ("EAX 2 not supported\n");
return SND_LOADED;//otherwise successful. It can be used for normal sound anyway.
return true;//otherwise successful. It can be used for normal sound anyway.
}
//worked. EAX is supported.
@ -903,7 +895,7 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
#endif
#endif
return SND_LOADED;
return true;
}
@ -915,23 +907,11 @@ static int DSOUND_Thread(void *arg)
{
soundcardinfo_t *sc = arg;
void *cond = sc->handle;
int cardnum = sc->audio_fd;
sc->handle = NULL;
//once creating the thread, the main thread will wait for us to signal that we have inited the dsound device.
switch(DSOUND_InitCard_Internal(sc, cardnum))
{
case SND_LOADED:
break;
case SND_NOMORE:
sc->audio_fd = -1;
if (!DSOUND_InitCard_Internal(sc, sc->name))
sc->selfpainting = false;
break;
default:
case SND_ERROR:
sc->selfpainting = false;
break;
}
//wake up the main thread.
Sys_ConditionSignal(cond);
@ -952,19 +932,17 @@ static int DSOUND_Thread(void *arg)
}
#endif
static int DSOUND_InitCard (soundcardinfo_t *sc, int cardnum)
static qboolean QDECL DSOUND_InitCard (soundcardinfo_t *sc, const char *device)
{
if (COM_CheckParm("-wavonly"))
return SND_NOMORE;
return false;
if (cardnum > 5)
return SND_NOMORE;
Q_strncpyz(sc->name, device?device:"", sizeof(sc->name));
#ifdef MULTITHREAD
if (snd_mixerthread.ival)
{
void *cond;
sc->audio_fd = cardnum;
sc->selfpainting = true;
sc->handle = cond = Sys_CreateConditional();
Sys_LockConditional(cond);
@ -972,7 +950,7 @@ static int DSOUND_InitCard (soundcardinfo_t *sc, int cardnum)
if (!sc->thread)
{
Con_SafePrintf ("Unable to create sound mixing thread\n");
return SND_NOMORE;
return false;
}
//wait for the thread to finish (along with all its error con printfs etc
@ -984,16 +962,48 @@ static int DSOUND_InitCard (soundcardinfo_t *sc, int cardnum)
{
Sys_WaitOnThread(sc->thread);
sc->thread = NULL;
return (sc->audio_fd==-1)?SND_NOMORE:SND_ERROR;
return false;
}
return SND_LOADED;
return true;
}
else
#endif
return DSOUND_InitCard_Internal(sc, cardnum);
return DSOUND_InitCard_Internal(sc, sc->name);
}
int (*pDSOUND_InitCard) (soundcardinfo_t *sc, int cardnum) = &DSOUND_InitCard;
#define SDRVNAME "DirectSound"
static BOOL (CALLBACK DSound_EnumCallback)(GUID FAR *guid, LPCSTR str1, LPCSTR str2, LPVOID parm)
{
char guidbuf[128];
wchar_t mssuck[128];
void (QDECL *callback) (const char *drivername, const char *devicecode, const char *readablename) = parm;
soundcardinfo_t *sc = parm;
if (guid == NULL) //we don't care about the (dupe) default device
return TRUE;
StringFromGUID2(guid, mssuck, sizeof(mssuck)/sizeof(mssuck[0]));
wcstombs(guidbuf, mssuck, sizeof(guidbuf));
callback(SDRVNAME, guidbuf, str1);
return TRUE;
}
static qboolean QDECL DSOUND_Enumerate(void (QDECL *cb) (const char *drivername, const char *devicecode, const char *readablename))
{
if (!DSOUND_InitOutputLibrary())
return false;
if (pDirectSoundEnumerate)
{
pDirectSoundEnumerate(&DSound_EnumCallback, cb);
return true;
}
return false;
}
sounddriver_t DSOUND_Output =
{
SDRVNAME,
DSOUND_InitCard,
DSOUND_Enumerate
};
#endif

View File

@ -112,10 +112,8 @@ cvar_t snd_linearresample_stream = CVARAF( "s_linearresample_stream", "0",
cvar_t snd_mixerthread = CVARAD( "s_mixerthread", "1",
"snd_mixerthread", "When enabled sound mixing will be run on a separate thread. Currently supported only by directsound. Other drivers may unconditionally thread audio. Set to 0 only if you have issues.");
cvar_t snd_usemultipledevices = CVARAFD( "s_multipledevices", "0",
"snd_multipledevices", 0, "If enabled, all output sound devices in your computer will be initialised for playback, not just the default device.");
cvar_t snd_driver = CVARAF( "s_driver", "",
"snd_driver", 0);
cvar_t snd_device = CVARAF( "s_device", "",
"snd_device", CVAR_ARCHIVE);
#ifdef VOICECHAT
static void S_Voip_Play_Callback(cvar_t *var, char *oldval);
@ -130,7 +128,7 @@ cvar_t cl_voip_play = CVARAFDC("cl_voip_play", "1", NULL, CVAR_ARCHIVE, "Enables
cvar_t cl_voip_ducking = CVARAFD("cl_voip_ducking", "0.5", NULL, CVAR_ARCHIVE, "Scales game audio by this much when someone is talking to you. Does not affect your speaker volume when you speak (minimum of cl_voip_capturingvol and cl_voip_ducking is used).");
cvar_t cl_voip_micamp = CVARAFDC("cl_voip_micamp", "2", NULL, CVAR_ARCHIVE, "Amplifies your microphone when using voip.", 0);
cvar_t cl_voip_codec = CVARAFDC("cl_voip_codec", "0", NULL, CVAR_ARCHIVE, "0: speex. 1: raw. 2: opus.", 0);
cvar_t cl_voip_noisefilter = CVARAFDC("cl_voip_noisefilter", "1", NULL, CVAR_ARCHIVE, "Enable the use of the noise cancelation filter, which also normalises microphone volume levels.", 0);
cvar_t cl_voip_noisefilter = CVARAFDC("cl_voip_noisefilter", "1", NULL, CVAR_ARCHIVE, "Enable the use of the noise cancelation filter.", 0);
cvar_t cl_voip_autogain = CVARAFDC("cl_voip_autogain", "0", NULL, CVAR_ARCHIVE, "Attempts to normalize your voice levels to a standard level. Useful for lazy people, but interferes with voice activation levels.", 0);
#endif
@ -471,6 +469,8 @@ static qboolean S_Opus_Init(void)
}
#endif
Con_Printf("OPUS support is experimental and should not be used\n"); //need to remove the packet length prefix.
s_voip.opus.loaded = true;
return s_voip.opus.loaded;
}
@ -508,6 +508,8 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
case VOIP_SPEEX_WIDE:
qspeex_decoder_destroy(s_voip.decoder[sender]);
break;
case VOIP_RAW:
break;
case VOIP_OPUS:
qopus_decoder_destroy(s_voip.decoder[sender]);
break;
@ -520,23 +522,34 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
{
default: //codec not supported.
return;
case VOIP_RAW:
s_voip.decsamplerate[sender] = 11025;
break;
case VOIP_SPEEX_OLD:
case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE:
if (!S_Speex_Init())
return; //speex not usable.
if (codec == VOIP_SPEEX_NARROW)
{
s_voip.decsamplerate[sender] = 8000;
s_voip.decframesize[sender] = 160;
}
else if (codec == VOIP_SPEEX_WIDE)
{
s_voip.decsamplerate[sender] = 16000;
s_voip.decframesize[sender] = 320;
}
else
{
s_voip.decsamplerate[sender] = 11025;
s_voip.decframesize[sender] = 160;
s_voip.decframesize[sender] = 160;
}
if (!s_voip.decoder[sender])
{
qspeex_bits_init(&s_voip.speex.decbits[sender]);
qspeex_bits_reset(&s_voip.speex.decbits[sender]);
s_voip.decoder[sender] = qspeex_decoder_init(codec==VOIP_SPEEX_WIDE?s_voip.speex.modewb:s_voip.speex.modenb);
s_voip.decoder[sender] = qspeex_decoder_init((codec==VOIP_SPEEX_WIDE)?s_voip.speex.modewb:s_voip.speex.modenb);
if (!s_voip.decoder[sender])
return;
}
@ -550,7 +563,6 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
//the lazy way to reset the codec!
if (!s_voip.decoder[sender])
{
s_voip.decframesize[sender] = (sizeof(decodebuf) / sizeof(decodebuf[0])) / 2; //this is the maximum size in a single frame.
//opus outputs to 8, 12, 16, 24, or 48khz. pick whichever has least excess samples and resample to fit it.
if (snd_speed <= 8000)
s_voip.decsamplerate[sender] = 8000;
@ -565,6 +577,8 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
s_voip.decoder[sender] = qopus_decoder_create(s_voip.decsamplerate[sender], 1/*FIXME: support stereo where possible*/, NULL);
if (!s_voip.decoder[sender])
return;
s_voip.decframesize[sender] = (sizeof(decodebuf) / sizeof(decodebuf[0])) / 2; //this is the maximum size in a single frame.
}
else
qopus_decoder_ctl(s_voip.decoder[sender], OPUS_RESET_STATE);
@ -596,7 +610,7 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
decodesamps += s_voip.decframesize[sender];
break;
case VOIP_OPUS:
r = qopus_decode(s_voip.decoder[sender], NULL, 0, decodebuf + decodesamps, sizeof(decodebuf)/sizeof(decodebuf[0]) - decodesamps, false);
r = qopus_decode(s_voip.decoder[sender], NULL, 0, decodebuf + decodesamps, min(s_voip.decframesize[sender], sizeof(decodebuf)/sizeof(decodebuf[0]) - decodesamps), false);
if (r > 0)
decodesamps += r;
break;
@ -606,7 +620,7 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
while (bytes > 0)
{
if (decodesamps + s_voip.decframesize[sender] > sizeof(decodebuf)/sizeof(decodebuf[0]))
if (decodesamps + s_voip.decframesize[sender] >= sizeof(decodebuf)/sizeof(decodebuf[0]))
{
S_RawAudio(sender, (qbyte*)decodebuf, s_voip.decsamplerate[sender], decodesamps, 1, 2, cl_voip_play.value);
decodesamps = 0;
@ -636,14 +650,43 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
decodesamps += s_voip.decframesize[sender];
s_voip.decseq[sender]++;
seq++;
if (decodesamps + s_voip.decframesize[sender] > sizeof(decodebuf)/sizeof(decodebuf[0]))
if (decodesamps + s_voip.decframesize[sender] >= sizeof(decodebuf)/sizeof(decodebuf[0]))
{
S_RawAudio(sender, (qbyte*)decodebuf, s_voip.decsamplerate[sender], decodesamps, 1, 2, cl_voip_play.value);
decodesamps = 0;
}
}
break;
case VOIP_RAW:
len = min(bytes, sizeof(decodebuf)-(sizeof(decodebuf[0])*decodesamps));
memcpy(decodebuf+decodesamps, start, len);
decodesamps += len / sizeof(decodebuf[0]);
s_voip.decseq[sender]++;
bytes -= len;
start += len;
break;
case VOIP_OPUS:
#if 1
len = bytes;
if (decodesamps > 0)
{
S_RawAudio(sender, (qbyte*)decodebuf, s_voip.decsamplerate[sender], decodesamps, 1, 2, cl_voip_play.value);
decodesamps = 0;
}
r = qopus_decode(s_voip.decoder[sender], start, len, decodebuf + decodesamps, sizeof(decodebuf)/sizeof(decodebuf[0]) - decodesamps, false);
Con_Printf("Decoded %i frames from %i bytes\n", r, len);
if (r > 0)
{
decodesamps += r;
s_voip.decseq[sender] += 1;//r / s_voip.decframesize[sender];
seq += 1;//r / s_voip.decframesize[sender];
}
else if (r < 0)
Con_Printf("Opus decoding error %i\n", r);
bytes -= len;
start += len;
#else
//FIXME: we shouldn't need this crap
bytes--;
len = *start++;
@ -661,6 +704,7 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
bytes -= len;
start += len;
#endif
break;
}
}
@ -718,6 +762,28 @@ void S_Voip_Parse(void)
S_Voip_Decode(sender, codec, gen, seq, bytes, data);
}
static float S_Voip_Preprocess(short *start, unsigned int samples, float micamp)
{
int i;
float level = 0, f;
int framesize = s_voip.encframesize;
while(samples >= framesize)
{
if (s_voip.speexdsp.preproc)
qspeex_preprocess_run(s_voip.speexdsp.preproc, start);
for (i = 0; i < framesize; i++)
{
f = start[i] * micamp;
start[i] = f;
f = fabs(start[i]);
level += f*f;
}
start += framesize;
samples -= framesize;
}
return level;
}
void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
{
unsigned char outbuf[8192];
@ -726,9 +792,8 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
short *start;
unsigned int initseq;//in frames
unsigned int inittimestamp;//in samples
unsigned int i;
unsigned int samps;
float level, f;
float level;
int len;
float micamp = cl_voip_micamp.value;
qboolean voipsendenable = true;
@ -822,7 +887,7 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
qspeex_bits_init(&s_voip.speex.encbits);
qspeex_bits_reset(&s_voip.speex.encbits);
s_voip.encoder = qspeex_encoder_init(voipcodec == VOIP_SPEEX_WIDE?s_voip.speex.modewb:s_voip.speex.modenb);
s_voip.encoder = qspeex_encoder_init((voipcodec == VOIP_SPEEX_WIDE)?s_voip.speex.modewb:s_voip.speex.modenb);
if (!s_voip.encoder)
return;
qspeex_encoder_ctl(s_voip.encoder, SPEEX_GET_FRAME_SIZE, &s_voip.encframesize);
@ -835,6 +900,10 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
s_voip.encsamplerate = 11025;
qspeex_encoder_ctl(s_voip.encoder, SPEEX_SET_SAMPLING_RATE, &s_voip.encsamplerate);
break;
case VOIP_RAW:
s_voip.encsamplerate = 11025;
s_voip.encframesize = 256;
break;
case VOIP_OPUS:
if (!S_Opus_Init())
{
@ -845,6 +914,7 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
//use whatever is convienient.
s_voip.encsamplerate = 48000;
s_voip.encframesize = s_voip.encsamplerate / 400; //2.5ms frames, at a minimum.
s_voip.encframesize *= 4; //go for 10ms
s_voip.encoder = qopus_encoder_create(s_voip.encsamplerate, 1, OPUS_APPLICATION_VOIP, NULL);
if (!s_voip.encoder)
return;
@ -907,6 +977,8 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
case VOIP_SPEEX_WIDE:
qspeex_bits_reset(&s_voip.speex.encbits);
break;
case VOIP_RAW:
break;
case VOIP_OPUS:
qopus_encoder_ctl(s_voip.encoder, OPUS_RESET_STATE);
break;
@ -960,21 +1032,17 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
s_voip.speexdsp.cursamplerate = s_voip.encsamplerate;
}
}
if (s_voip.speexdsp.preproc)
qspeex_preprocess_run(s_voip.speexdsp.preproc, start);
}
for (i = 0; i < s_voip.encframesize; i++)
else if (s_voip.speexdsp.preproc)
{
f = start[i] * micamp;
start[i] = f;
f = fabs(start[i]);
level += f*f;
qspeex_preprocess_state_destroy(s_voip.speexdsp.preproc);
s_voip.speexdsp.preproc = NULL;
}
switch(s_voip.enccodec)
{
case VOIP_SPEEX_OLD:
level += S_Voip_Preprocess(start, s_voip.encframesize, micamp);
qspeex_bits_reset(&s_voip.speex.encbits);
qspeex_encode_int(s_voip.encoder, start, &s_voip.speex.encbits);
len = qspeex_bits_write(&s_voip.speex.encbits, outbuf+(outpos+1), sizeof(outbuf) - (outpos+1));
@ -983,7 +1051,6 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
outbuf[outpos] = len;
outpos += 1+len;
s_voip.encsequence++;
s_voip.enctimestamp += s_voip.encframesize;
samps+=s_voip.encframesize;
encpos += s_voip.encframesize*2;
break;
@ -993,19 +1060,76 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
for (; s_voip.capturepos-encpos >= s_voip.encframesize*2 && sizeof(outbuf)-outpos > 64; )
{
start = (short*)(s_voip.capturebuf + encpos);
level += S_Voip_Preprocess(start, s_voip.encframesize, micamp);
qspeex_encode_int(s_voip.encoder, start, &s_voip.speex.encbits);
s_voip.encsequence++;
samps+=s_voip.encframesize;
s_voip.enctimestamp += s_voip.encframesize;
encpos += s_voip.encframesize*2;
if (rtpstream)
if (rtpstream) //FIXME: why?
break;
}
len = qspeex_bits_write(&s_voip.speex.encbits, outbuf+outpos, sizeof(outbuf) - outpos);
outpos += len;
break;
case VOIP_RAW:
len = s_voip.capturepos-encpos; //amount of data to be eaten in this frame
len = min(len, sizeof(outbuf)-outpos);
len &= ~((s_voip.encframesize*2)-1);
level += S_Voip_Preprocess(start, len/2, micamp);
memcpy(outbuf+outpos, start, len); //'encode'
outpos += len; //bytes written to output
encpos += len; //number of bytes consumed
s_voip.encsequence++; //increment number of packets, for packetloss detection.
samps+=len / 2; //number of samplepairs eaten in this packet. for stats.
break;
case VOIP_OPUS:
#if 1
{
//opus rtp only supports/allows a single chunk in each packet.
int frames;
//densely pack the frames.
start = (short*)(s_voip.capturebuf + encpos);
frames = (s_voip.capturepos-encpos)/2;
frames = s_voip.encframesize;
if (frames >= 2880)
frames = 2880;
else if (frames >= 1920)
frames = 1920;
else if (frames >= 960)
frames = 960;
else if (frames >= 480)
frames = 480;
else if (frames >= 240)
frames = 240;
else if (frames >= 120)
frames = 120;
else
{
Con_Printf("invalid Opus frame size\n");
frames = 0;
}
Con_Printf("Encoding %i frames", frames);
level += S_Voip_Preprocess(start, frames, micamp);
len = qopus_encode(s_voip.encoder, start, frames, outbuf+outpos, sizeof(outbuf) - outpos);
Con_Printf(" (%i bytes)\n", len);
if (len >= 0)
{
s_voip.encsequence += frames / s_voip.encframesize;
outpos += len;
samps+=frames;
encpos += frames*2;
}
else
{
Con_Printf("Opus encoding error: %i\n", len);
encpos = s_voip.capturepos;
}
}
break;
#else
level += S_Voip_Preprocess(start, s_voip.encframesize, micamp);
len = qopus_encode(s_voip.encoder, start, s_voip.encframesize, outbuf+(outpos+1), max(255, sizeof(outbuf) - (outpos+1)));
if (len == 1) //packet does not need to be transmitted if it returns 1, supposedly. crazyness.
len = 0;
@ -1021,20 +1145,21 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
}
s_voip.encsequence++;
samps+=s_voip.encframesize;
s_voip.enctimestamp += s_voip.encframesize;
encpos += s_voip.encframesize*2;
break;
#endif
default:
outbuf[outpos] = 0;
break;
}
if (rtpstream)
if (rtpstream || s_voip.enccodec == VOIP_OPUS)
break;
}
if (samps)
{
float nl;
s_voip.enctimestamp += samps;
nl = (3000*level) / (32767.0f*32767*samps);
s_voip.voiplevel = (s_voip.voiplevel*7 + nl)/8;
if (s_voip.voiplevel < cl_voip_vad_threshhold.ival && !(cl_voip_send.ival & 6))
@ -1188,134 +1313,6 @@ void S_Voip_Parse(void)
#endif
sounddriver pOPENAL_InitCard;
sounddriver pDSOUND_InitCard;
sounddriver pALSA_InitCard;
sounddriver pSNDIO_InitCard;
sounddriver pOSS_InitCard;
sounddriver pMacOS_InitCard;
sounddriver pSDL_InitCard;
sounddriver pWAV_InitCard;
sounddriver pDroid_InitCard;
sounddriver pAHI_InitCard;
#ifdef NACL
extern sounddriver pPPAPI_InitCard;
#endif
typedef struct {
char *name;
sounddriver *ptr;
} sdriver_t;
sdriver_t drivers[] = {
//in order of preference
{"OpenAL", &pOPENAL_InitCard}, //yay, get someone else to sort out sound support, woot
{"DSound", &pDSOUND_InitCard}, //prefered on windows
{"MacOS", &pMacOS_InitCard}, //prefered on mac
{"Droid", &pDroid_InitCard}, //prefered on android (java thread)
{"AHI", &pAHI_InitCard}, //prefered on morphos
#ifdef NACL
{"PPAPI", &pPPAPI_InitCard}, //google's native client
#endif
{"SNDIO", &pSNDIO_InitCard}, //prefered on OpenBSD
{"SDL", &pSDL_InitCard}, //prefered on linux
{"ALSA", &pALSA_InitCard}, //pure shite
{"OSS", &pOSS_InitCard}, //good, but not likely to work any more
{"WaveOut", &pWAV_InitCard}, //doesn't work properly in vista, etc.
{NULL, NULL}
};
static int SNDDMA_Init(soundcardinfo_t *sc, int *cardnum, int *drivernum)
{
sdriver_t *sd;
int st = 0;
memset(sc, 0, sizeof(*sc));
// set requested rate
if (snd_khz.ival >= 1000)
sc->sn.speed = snd_khz.ival;
else if (snd_khz.ival <= 0)
sc->sn.speed = 22050;
/* else if (snd_khz.ival >= 195)
sc->sn.speed = 200000;
else if (snd_khz.ival >= 180)
sc->sn.speed = 192000;
else if (snd_khz.ival >= 90)
sc->sn.speed = 96000; */
else if (snd_khz.ival >= 45)
sc->sn.speed = 48000;
else if (snd_khz.ival >= 30)
sc->sn.speed = 44100;
else if (snd_khz.ival >= 20)
sc->sn.speed = 22050;
else if (snd_khz.ival >= 10)
sc->sn.speed = 11025;
else
sc->sn.speed = 8000;
// set requested speaker count
if (snd_speakers.ival > MAXSOUNDCHANNELS)
sc->sn.numchannels = MAXSOUNDCHANNELS;
else if (snd_speakers.ival > 1)
sc->sn.numchannels = (int)snd_speakers.ival;
else
sc->sn.numchannels = 1;
// set requested sample bits
if (snd_samplebits.ival >= 16)
sc->sn.samplebits = 16;
else
sc->sn.samplebits = 8;
// set requested buffer size
if (snd_buffersize.ival > 0)
sc->sn.samples = snd_buffersize.ival * sc->sn.numchannels;
else
sc->sn.samples = 0;
if (*snd_driver.string)
{
if (*drivernum)
return 2;
for (sd = drivers; sd->name; sd++)
if (!Q_strcasecmp(sd->name, snd_driver.string))
break;
}
else
sd = &drivers[*drivernum];
if (!sd->ptr)
return 2; //no more cards.
if (!*sd->ptr) //driver not loaded
{
Con_DPrintf("Sound driver %s is not loaded\n", sd->name);
st = 2;
}
else
{
Con_DPrintf("Trying to load a %s sound device\n", sd->name);
st = (**sd->ptr)(sc, *cardnum);
}
if (st == 1) //worked
{
*cardnum += 1; //use the next card next time
return st;
}
else if (st == 0) //failed, try the next card with this driver.
{
*cardnum += 1;
return SNDDMA_Init(sc, cardnum, drivernum);
}
else //card number wasn't valid, try the first card of the next driver
{
*cardnum = 0;
*drivernum += 1;
return SNDDMA_Init(sc, cardnum, drivernum);
}
}
void S_DefaultSpeakerConfiguration(soundcardinfo_t *sc)
{
@ -1370,6 +1367,211 @@ void S_DefaultSpeakerConfiguration(soundcardinfo_t *sc)
}
sounddriver_t DSOUND_Output;
sounddriver_t OPENAL_Output;
sounddriver pALSA_InitCard;
sounddriver pSNDIO_InitCard;
sounddriver pOSS_InitCard;
sounddriver pMacOS_InitCard;
sounddriver pSDL_InitCard;
sounddriver pWAV_InitCard;
sounddriver pDroid_InitCard;
sounddriver pAHI_InitCard;
#ifdef NACL
extern sounddriver pPPAPI_InitCard;
#endif
//in order of preference
sounddriver_t *outputdrivers[] =
{
&OPENAL_Output,
&DSOUND_Output,
NULL
};
typedef struct {
char *name;
sounddriver *ptr;
} sdriver_t;
sdriver_t olddrivers[] = {
//in order of preference
{"MacOS", &pMacOS_InitCard}, //prefered on mac
{"Droid", &pDroid_InitCard}, //prefered on android (java thread)
{"AHI", &pAHI_InitCard}, //prefered on morphos
#ifdef NACL
{"PPAPI", &pPPAPI_InitCard}, //google's native client
#endif
{"SNDIO", &pSNDIO_InitCard}, //prefered on OpenBSD
{"SDL", &pSDL_InitCard}, //prefered on linux
{"ALSA", &pALSA_InitCard}, //pure shite
{"OSS", &pOSS_InitCard}, //good, but not likely to work any more
{"WaveOut", &pWAV_InitCard}, //doesn't work properly in vista, etc.
{NULL, NULL}
};
static soundcardinfo_t *SNDDMA_Init(char *driver, char *device)
{
soundcardinfo_t *sc = Z_Malloc(sizeof(soundcardinfo_t));
sdriver_t *od;
sounddriver_t *sd;
int i;
int st;
memset(sc, 0, sizeof(*sc));
// set requested rate
if (snd_khz.ival >= 1000)
sc->sn.speed = snd_khz.ival;
else if (snd_khz.ival <= 0)
sc->sn.speed = 22050;
/* else if (snd_khz.ival >= 195)
sc->sn.speed = 200000;
else if (snd_khz.ival >= 180)
sc->sn.speed = 192000;
else if (snd_khz.ival >= 90)
sc->sn.speed = 96000; */
else if (snd_khz.ival >= 45)
sc->sn.speed = 48000;
else if (snd_khz.ival >= 30)
sc->sn.speed = 44100;
else if (snd_khz.ival >= 20)
sc->sn.speed = 22050;
else if (snd_khz.ival >= 10)
sc->sn.speed = 11025;
else
sc->sn.speed = 8000;
// set requested speaker count
if (snd_speakers.ival > MAXSOUNDCHANNELS)
sc->sn.numchannels = MAXSOUNDCHANNELS;
else if (snd_speakers.ival > 1)
sc->sn.numchannels = (int)snd_speakers.ival;
else
sc->sn.numchannels = 1;
// set requested sample bits
if (snd_samplebits.ival >= 16)
sc->sn.samplebits = 16;
else
sc->sn.samplebits = 8;
// set requested buffer size
if (snd_buffersize.ival > 0)
sc->sn.samples = snd_buffersize.ival * sc->sn.numchannels;
else
sc->sn.samples = 0;
for (i = 0; outputdrivers[i]; i++)
{
sd = outputdrivers[i];
if (sd && !driver || !Q_strcasecmp(sd->name, driver))
{
//skip drivers which are not present.
if (!sd->InitCard)
continue;
st = (**sd->InitCard)(sc, device);
if (st)
{
S_DefaultSpeakerConfiguration(sc);
if (sndcardinfo)
{ //if the sample speeds of multiple soundcards do not match, it'll fail.
if (snd_speed != sc->sn.speed)
{
Con_Printf("S_Startup: Ignoring soundcard %s due to mismatched sample speeds.\nTry running Quake with -singlesound to use just the primary soundcard\n", sc->name);
S_ShutdownCard(sc);
continue;
}
}
else
snd_speed = sc->sn.speed;
sc->next = sndcardinfo;
sndcardinfo = sc;
return sc;
}
}
}
for (i = 0; olddrivers[i].name; i++)
{
od = &olddrivers[i];
if (!driver || !Q_strcasecmp(od->name, driver))
{
//skip drivers which are not present.
if (!*od->ptr)
continue;
st = (**od->ptr)(sc, device?atoi(device):0);
if (st == 1)
{
S_DefaultSpeakerConfiguration(sc);
if (sndcardinfo)
{ //if the sample speeds of multiple soundcards do not match, it'll fail.
if (snd_speed != sc->sn.speed)
{
Con_Printf("S_Startup: Ignoring soundcard %s due to mismatched sample speeds.\nTry running Quake with -singlesound to use just the primary soundcard\n", sc->name);
S_ShutdownCard(sc);
continue;
}
}
else
snd_speed = sc->sn.speed;
sc->next = sndcardinfo;
sndcardinfo = sc;
return sc;
}
}
}
Z_Free(sc);
Con_Printf("Could not start \"%s\" device \"%s\"\n", driver?driver:"audio", device?device:"default");
return NULL;
}
int numsoundoutdevices;
char **soundoutdevicecodes;
char **soundoutdevicenames;
void QDECL S_EnumeratedOutDevice(const char *driver, const char *devicecode, const char *readabledevice)
{
const char *fullintname;
if (devicecode && strchr(devicecode, ' '))
fullintname = va("\"%s:%s\"", driver, devicecode);
else if (devicecode)
fullintname = va("%s:%s", driver, devicecode);
else
fullintname = driver;
soundoutdevicecodes = realloc(soundoutdevicecodes, (numsoundoutdevices+2) * sizeof(char*));
soundoutdevicecodes[numsoundoutdevices] = strdup(fullintname);
soundoutdevicecodes[numsoundoutdevices+1] = NULL;
soundoutdevicenames = realloc(soundoutdevicenames, (numsoundoutdevices+2) * sizeof(char*));
soundoutdevicenames[numsoundoutdevices] = strdup(readabledevice);
soundoutdevicenames[numsoundoutdevices+1] = NULL;
numsoundoutdevices++;
}
void S_EnumerateDevices(void)
{
int i;
sounddriver_t *sd;
numsoundoutdevices = 0;
S_EnumeratedOutDevice("", NULL, "Default");
for (i = 0; outputdrivers[i]; i++)
{
sd = outputdrivers[i];
if (sd && sd->name)
{
if (!sd->Enumerate || !sd->Enumerate(S_EnumeratedOutDevice))
S_EnumeratedOutDevice(sd->name, "", va("Default %s", sd->name));
}
}
}
/*
================
S_Startup
@ -1379,10 +1581,7 @@ S_Startup
void S_ClearRaw(void);
void S_Startup (void)
{
int cardnum, drivernum;
int warningmessage=0;
int rc;
soundcardinfo_t *sc;
char *s;
if (!snd_initialized)
return;
@ -1393,51 +1592,22 @@ void S_Startup (void)
snd_blocked = 0;
snd_speed = 0;
for(cardnum = 0, drivernum = 0;;)
for (s = snd_device.string; ; )
{
sc = Z_Malloc(sizeof(soundcardinfo_t));
rc = SNDDMA_Init(sc, &cardnum, &drivernum);
if (!rc) //error stop
{
Con_Printf("S_Startup: SNDDMA_Init failed.\n");
Z_Free(sc);
char *sep;
s = COM_Parse(s);
if (!*com_token)
break;
}
if (rc == 2) //silently stop (no more cards)
{
Z_Free(sc);
break;
}
S_DefaultSpeakerConfiguration(sc);
if (sndcardinfo)
{ //if the sample speeds of multiple soundcards do not match, it'll fail.
if (snd_speed != sc->sn.speed)
{
if (!warningmessage)
{
Con_Printf("S_Startup: Ignoring soundcard %s due to mismatched sample speeds.\nTry running Quake with -singlesound to use just the primary soundcard\n", sc->name);
S_ShutdownCard(sc);
warningmessage = true;
}
Z_Free(sc);
continue;
}
}
else
snd_speed = sc->sn.speed;
sc->next = sndcardinfo;
sndcardinfo = sc;
if (!snd_usemultipledevices.ival)
break;
sep = strchr(com_token, ':');
if (sep)
*sep++ = 0;
SNDDMA_Init(com_token, sep);
}
if (!sndcardinfo)
SNDDMA_Init(NULL, NULL);
sound_started = true;//!!sndcardinfo;
sound_started = true;
S_ClearRaw();
@ -1506,29 +1676,6 @@ void S_Control_f (void)
S_Shutdown();
sound_started = 0;
}
else if (!Q_strcasecmp(command, "multi") || !Q_strcasecmp(command, "multiple"))
{
if (!Q_strcasecmp(Cmd_Argv (2), "off"))
{
if (snd_usemultipledevices.ival)
{
Cvar_SetValue(&snd_usemultipledevices, 0);
S_Restart_f();
}
}
else if (!snd_usemultipledevices.ival)
{
Cvar_SetValue(&snd_usemultipledevices, 1);
S_Restart_f();
}
return;
}
if (!Q_strcasecmp(command, "single"))
{
Cvar_SetValue(&snd_usemultipledevices, 0);
S_Restart_f();
return;
}
if (!Q_strcasecmp(command, "rate") || !Q_strcasecmp(command, "speed"))
{
@ -1612,6 +1759,8 @@ void S_Init (void)
{
int p;
S_EnumerateDevices();
Con_DPrintf("\nSound Initialization\n");
Cmd_AddCommand("play", S_Play);
@ -1653,8 +1802,7 @@ void S_Init (void)
Cvar_Register(&snd_mixerthread, "Sound controls");
#endif
Cvar_Register(&snd_playersoundvolume, "Sound controls");
Cvar_Register(&snd_usemultipledevices, "Sound controls");
Cvar_Register(&snd_driver, "Sound controls");
Cvar_Register(&snd_device, "Sound controls");
Cvar_Register(&snd_linearresample, "Sound controls");
Cvar_Register(&snd_linearresample_stream, "Sound controls");
@ -1687,12 +1835,6 @@ void S_Init (void)
Sys_Error ("S_Init: you must specify a speed in KB after -soundspeed");
}
if (COM_CheckParm ("-nomultipledevices") || COM_CheckParm ("-singlesound"))
Cvar_SetValue(&snd_usemultipledevices, 0);
if (COM_CheckParm ("-multisound"))
Cvar_SetValue(&snd_usemultipledevices, 1);
snd_initialized = true;
known_sfx = Z_Malloc(MAX_SFX*sizeof(sfx_t));
@ -1740,6 +1882,17 @@ void S_Shutdown(void)
Z_Free(known_sfx);
known_sfx = NULL;
num_sfx = 0;
while (numsoundoutdevices)
{
numsoundoutdevices--;
free(soundoutdevicenames[numsoundoutdevices]);
free(soundoutdevicecodes[numsoundoutdevices]);
}
free(soundoutdevicenames);
soundoutdevicenames = NULL;
free(soundoutdevicecodes);
soundoutdevicecodes = NULL;
}
@ -2034,7 +2187,7 @@ static void S_StartSoundCard(soundcardinfo_t *sc, int entnum, int entchannel, sf
target_chan->entchannel = entchannel;
SND_Spatialize(sc, target_chan);
if (!target_chan->vol[0] && !target_chan->vol[1] && !target_chan->vol[2] && !target_chan->vol[3] && !target_chan->vol[4] && !target_chan->vol[5])
if (!target_chan->vol[0] && !target_chan->vol[1] && !target_chan->vol[2] && !target_chan->vol[3] && !target_chan->vol[4] && !target_chan->vol[5] && sc->ChannelUpdate)
return; // not audible at all
// new channel
@ -2434,9 +2587,9 @@ static void S_UpdateCard(soundcardinfo_t *sc)
}
#ifdef AVAIL_OPENAL
if (sc->openal == 1)
if (sc->ListenerUpdate)
{
OpenAL_Update_Listener(listener_origin, listener_forward, listener_right, listener_up, listener_velocity);
sc->ListenerUpdate(sc, listener_origin, listener_forward, listener_right, listener_up, listener_velocity);
}
#endif
@ -2974,6 +3127,8 @@ void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels,
if (si->channel[i].pos < 0)
si->channel[i].pos = 0;
if (si->ChannelUpdate)
si->ChannelUpdate(si, &si->channel[i], false);
break;
}
if (i == si->total_chans) //this one wasn't playing.
@ -2990,6 +3145,9 @@ void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels,
c->sfx = &s->sfx;
c->start = 0;
SND_Spatialize(si, c);
if (si->ChannelUpdate)
si->ChannelUpdate(si, &si->channel[i], true);
}
}
S_UnlockMixer();

View File

@ -190,9 +190,6 @@ void SNDVC_MicInput(qbyte *buffer, int samples, int freq, int width);
#ifdef AVAIL_OPENAL
void OpenAL_LoadCache(sfx_t *s, sfxcache_t *sc);
void OpenAL_StartSound(int entnum, int entchannel, sfx_t * sfx, vec3_t origin, float fvol, float attenuation, float pitchscale);
void OpenAL_Update_Listener(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up, vec3_t velocity);
void OpenAL_CvarInit(void);
#endif
@ -236,7 +233,6 @@ extern cvar_t snd_capture;
extern float voicevolumemod;
extern qboolean snd_initialized;
extern cvar_t snd_usemultipledevices;
extern cvar_t snd_mixerthread;
extern int snd_blocked;
@ -254,6 +250,12 @@ void S_AmbientOn (void);
//inititalisation functions.
typedef struct
{
const char *name; //must be a single token, with no :
qboolean (QDECL *InitCard) (soundcardinfo_t *sc, const char *cardname); //NULL for default device.
qboolean (QDECL *Enumerate) (void (QDECL *callback) (const char *drivername, const char *devicecode, const char *readablename));
} sounddriver_t;
typedef int (*sounddriver) (soundcardinfo_t *sc, int cardnum);
extern sounddriver pOPENAL_InitCard;
extern sounddriver pDSOUND_InitCard;
@ -296,6 +298,7 @@ struct soundcardinfo_s { //windows has one defined AFTER directsound
void (*SetWaterDistortion) (soundcardinfo_t *sc, qboolean underwater); //if you have eax enabled, change the environment. fixme. generally this is a stub. optional.
void (*Restore) (soundcardinfo_t *sc); //called before lock/unlock/lock/unlock/submit. optional
void (*ChannelUpdate) (soundcardinfo_t *sc, channel_t *channel, unsigned int schanged); //properties of a sound effect changed. this is to notify hardware mixers. optional.
void (*ListenerUpdate) (soundcardinfo_t *sc, vec3_t origin, vec3_t forward, vec3_t right, vec3_t up, vec3_t velocity); //player moved or something. this is to notify hardware mixers. optional.
//driver-specific - if you need more stuff, you should just shove it in the handle pointer
void *thread;
@ -303,11 +306,6 @@ struct soundcardinfo_s { //windows has one defined AFTER directsound
int snd_sent;
int snd_completed;
int audio_fd;
// no clue how else to handle this yet!
#ifdef AVAIL_OPENAL
int openal;
#endif
};
extern soundcardinfo_t *sndcardinfo;

View File

@ -2421,7 +2421,10 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
cds.cbData = strlen(qtvfile);
cds.lpData = (void*)qtvfile;
if (SendMessage(old, WM_COPYDATA, (WPARAM)GetDesktopWindow(), (LPARAM)&cds))
{
Sleep(10*1000); //sleep for 10 secs so the real engine has a chance to open it, if the program that gave it is watching to see if we quit.
return 0; //message sent.
}
}
}
else

View File

@ -1250,37 +1250,8 @@ void V_CalcRefdef (playerview_t *pv)
r_refdef.vieworg[1] += 1.0/16;
r_refdef.vieworg[2] += 1.0/16;
if (pv->fixangle)
{
if (pv->oldfixangle)
{
float frac, move;
if (cl.gametime <= cl.oldgametime)
frac = 1;
else
{
frac = (realtime - cl.gametimemark) / (cl.gametime - cl.oldgametime);
frac = bound(0, frac, 1);
}
for (i = 0; i < 3; i++)
{
move = pv->fixangles[i] - pv->oldfixangles[i];
if (move >= 180)
move -= 360;
if (move <= -180)
move += 360;
r_refdef.viewangles[i] = pv->oldfixangles[i] + frac * move;
}
}
else
{
VectorCopy (pv->fixangles, r_refdef.viewangles);
}
}
else
{
VectorCopy (pv->simangles, r_refdef.viewangles);
}
VectorCopy (pv->simangles, r_refdef.viewangles);
V_CalcViewRoll (pv);
V_AddIdle (pv);
@ -1685,7 +1656,6 @@ void V_RenderView (void)
SCR_VRectForPlayer(&r_refdef.grect, viewnum);
V_RenderPlayerViews(r_refdef.playerview);
GL_Set2D (false);
Plug_SBar(r_refdef.playerview);
SCR_TileClear ();
}

View File

@ -95,7 +95,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define AVAIL_OGGVORBIS
/* Jogi's OpenAL support */
// #define AVAIL_OPENAL
#define AVAIL_OPENAL
#endif
#if defined(MINGW) || defined(MACOSX)

View File

@ -2679,7 +2679,7 @@ void Cmd_set_f(void)
{
Cmd_ShiftArgs(1, false);
text = Cmd_Args();
if (*text == '\"') //if it's already quoted, dequote it, and ignore trailing stuff, for q2/q3 compatability
if (*text == '\"' || (*text == '\\' && text[1] == '\"')) //if it's already quoted, dequote it, and ignore trailing stuff, for q2/q3 compatability
text = Cmd_Argv(1);
else
{

View File

@ -5737,6 +5737,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer)
byte_vec4_t *oindex;
float *opose,*oposebase;
vec2_t *otcoords;
int memsize;
galiasinfo_t *gai;
@ -5846,13 +5847,16 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer)
mesh = (struct iqmmesh*)(buffer + h->ofs_meshes);
/*allocate a nice big block of memory and figure out where stuff is*/
gai = ZG_Malloc(&loadmodel->memgroup, sizeof(*gai)*h->num_meshes +
memsize = sizeof(*gai)*h->num_meshes;
memsize += sizeof(*fgroup)*numgroups + sizeof(float)*12*(h->num_joints + (h->num_poses*h->num_frames)) + sizeof(*bones)*h->num_joints;
memsize += (sizeof(*opos) + sizeof(*onorm1) + sizeof(*onorm2) + sizeof(*onorm3) + sizeof(*otcoords) + (noweights?0:(sizeof(*oindex)+sizeof(*oweight)))) * h->num_vertexes;
#ifndef SERVERONLY
sizeof(*skin)*h->num_meshes + sizeof(*shaders)*h->num_meshes +
memsize += sizeof(*skin)*h->num_meshes + sizeof(*shaders)*h->num_meshes;
#endif
sizeof(*fgroup)*numgroups + sizeof(float)*12*(h->num_joints + (h->num_poses*h->num_frames)) + sizeof(*bones)*h->num_joints +
(sizeof(*opos) + sizeof(*onorm1) + sizeof(*onorm2) + sizeof(*onorm3) + sizeof(*otcoords) + (noweights?0:(sizeof(*oindex)+sizeof(*oweight)))) * h->num_vertexes);
/*allocate a nice big block of memory and figure out where stuff is*/
gai = ZG_Malloc(&loadmodel->memgroup, memsize);
bones = (galiasbone_t*)(gai + h->num_meshes);
opos = (vecV_t*)(bones + h->num_joints);
onorm3 = (vec3_t*)(opos + h->num_vertexes);

View File

@ -3060,6 +3060,7 @@ skipwhite:
}
#endif
//semi-colon delimited tokens
char *COM_ParseStringSet (const char *data)
{
int c;
@ -3243,6 +3244,10 @@ skipwhite:
goto skipwhite;
}
if (c == '\\' && data[1] == '\"')
{
return COM_ParseCString(data+1, token, tokenlen);
}
// handle quoted strings specially
if (c == '\"')
@ -3506,13 +3511,73 @@ skipwhite:
return (char*)data;
}
char *COM_ParseCString (const char *data)
const char *COM_QuotedString(const char *string, char *buf, int buflen)
{
const char *result = buf;
if (strchr(string, '\r') || strchr(string, '\n') || strchr(string, '\"'))
{
*buf++ = '\\'; //prefix so the reader knows its a quoted string.
*buf++ = '\"'; //opening quote
buflen -= 4;
while(*string && buflen >= 2)
{
switch(*string)
{
case '\n':
*buf++ = '\\';
*buf++ = 'n';
break;
case '\r':
*buf++ = '\\';
*buf++ = 'r';
break;
case '\'':
*buf++ = '\\';
*buf++ = '\'';
break;
case '\"':
*buf++ = '\\';
*buf++ = '\"';
break;
case '\\':
*buf++ = '\\';
*buf++ = '\\';
break;
case '$':
*buf++ = '\\';
*buf++ = '$';
break;
default:
*buf++ = *string;
break;
}
string++;
}
*buf++ = '\"'; //closing quote
*buf++ = 0;
return result;
}
else
{
*buf++ = '\"'; //opening quote
buflen -= 3;
while(*string && buflen >= 0)
{
*buf++ = *string++;
}
*buf++ = '\"'; //closing quote
*buf++ = 0;
return result;
}
}
char *COM_ParseCString (const char *data, char *token, int tokenlen)
{
int c;
int len;
len = 0;
com_token[0] = 0;
token[0] = 0;
if (!data)
return NULL;
@ -3544,16 +3609,16 @@ skipwhite:
data++;
while (1)
{
if (len >= TOKENSIZE-2)
if (len >= tokenlen-2)
{
com_token[len] = '\0';
token[len] = '\0';
return (char*)data;
}
c = *data++;
if (!c)
{
com_token[len] = 0;
token[len] = 0;
return (char*)data;
}
if (c == '\\')
@ -3561,28 +3626,37 @@ skipwhite:
c = *data++;
switch(c)
{
case '\r':
if (*data == '\n')
data++;
case '\n':
continue;
case 'n':
c = '\n';
break;
case 'r':
c = '\r';
break;
case '$':
case '\\':
c = '\\';
case '\'':
break;
case '"':
c = '"';
com_token[len] = c;
token[len] = c;
len++;
continue;
default:
com_token[len] = 0;
return (char*)data;
c = '?';
break;
}
}
if (c=='\"' || !c)
{
com_token[len] = 0;
token[len] = 0;
return (char*)data;
}
com_token[len] = c;
token[len] = c;
len++;
}
}
@ -3590,15 +3664,15 @@ skipwhite:
// parse a regular word
do
{
if (len >= sizeof(com_token)-1)
if (len >= tokenlen-1)
break;
com_token[len] = c;
token[len] = c;
data++;
len++;
c = *data;
} while (c>32);
com_token[len] = 0;
token[len] = 0;
return (char*)data;
}

View File

@ -273,10 +273,11 @@ extern qboolean com_eof;
#define COM_Parse(d) COM_ParseOut(d,com_token, sizeof(com_token))
char *COM_ParseOut (const char *data, char *out, int outlen);
char *COM_ParseStringSet (const char *data);
char *COM_ParseCString (const char *data);
char *COM_ParseCString (const char *data, char *out, int outlen);
char *COM_StringParse (const char *data, char *token, unsigned int tokenlen, qboolean expandmacros, qboolean qctokenize);
char *COM_ParseToken (const char *data, const char *punctuation);
char *COM_TrimString(char *str);
const char *COM_QuotedString(const char *string, char *buf, int buflen); //inverse of COM_StringParse
extern int com_argc;

View File

@ -1104,6 +1104,7 @@ qboolean Cvar_Command (int level)
{
cvar_t *v;
char *str;
char buffer[65536];
// check variables
v = Cvar_FindVar (Cmd_Argv(0));
@ -1128,29 +1129,29 @@ qboolean Cvar_Command (int level)
{
if (v->flags & CVAR_LATCH)
{
Con_Printf ("\"%s\" is currently \"%s\"\n", v->name, v->string);
Con_Printf ("Will be changed to \"%s\" on the next map\n", v->latched_string);
Con_Printf ("\"%s\" is currently %s\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer)));
Con_Printf ("Will be changed to %s on the next map\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer)));
}
else if (v->flags & CVAR_RENDERERLATCH)
{
Con_Printf ("\"%s\" is \"%s\"\n", v->name, v->string);
Con_Printf ("Will be changed to \"%s\" on vid_restart\n", v->latched_string);
Con_Printf ("\"%s\" is %s\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer)));
Con_Printf ("Will be changed to %s on vid_restart\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer)));
}
else
{
Con_Printf ("\"%s\" is \"%s\"\n", v->name, v->latched_string);
Con_Printf ("Effective value is \"%s\"\n", v->string);
Con_Printf ("\"%s\" is %s\n", v->name, COM_QuotedString(v->latched_string, buffer, sizeof(buffer)));
Con_Printf ("Effective value is %s\n", COM_QuotedString(v->string, buffer, sizeof(buffer)));
}
Con_Printf("Default: \"%s\"\n", v->defaultstr);
Con_Printf("Default: \"%s\"\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer)));
}
else
{
if (!strcmp(v->string, v->defaultstr))
Con_Printf ("\"%s\" is \"%s\" (default)\n", v->name, v->string);
Con_Printf ("\"%s\" is %s (default)\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer)));
else
{
Con_Printf ("\"%s\" is \"%s\"\n", v->name, v->string);
Con_Printf("Default: \"%s\"\n", v->defaultstr);
Con_Printf ("\"%s\" is %s\n", v->name, COM_QuotedString(v->string, buffer, sizeof(buffer)));
Con_Printf("Default: %s\n", COM_QuotedString(v->defaultstr, buffer, sizeof(buffer)));
}
}
return true;
@ -1170,7 +1171,7 @@ qboolean Cvar_Command (int level)
#ifndef SERVERONLY
if (Cmd_ExecLevel > RESTRICT_SERVER)
{ //directed at a secondary player.
CL_SendClientCommand(true, "%i setinfo %s \"%s\"", Cmd_ExecLevel - RESTRICT_SERVER-1, v->name, str);
CL_SendClientCommand(true, "%i setinfo %s %s", Cmd_ExecLevel - RESTRICT_SERVER-1, v->name, COM_QuotedString(str, buffer, sizeof(buffer)));
return true;
}
@ -1221,6 +1222,7 @@ void Cvar_WriteVariables (vfsfile_t *f, qboolean all)
cvar_t *var;
char *val;
char *s;
char buffer[65536];
for (grp=cvar_groups ; grp ; grp=grp->next)
{
@ -1242,12 +1244,12 @@ void Cvar_WriteVariables (vfsfile_t *f, qboolean all)
if (var->flags & CVAR_USERCREATED)
{
if (var->flags & CVAR_ARCHIVE)
s = va("seta %s \"%s\"\n", var->name, val);
s = va("seta %s %s\n", var->name, COM_QuotedString(val, buffer, sizeof(buffer)));
else
s = va("set %s \"%s\"\n", var->name, val);
s = va("set %s %s\n", var->name, COM_QuotedString(val, buffer, sizeof(buffer)));
}
else
s = va("%s \"%s\"\n", var->name, val);
s = va("%s %s\n", var->name, COM_QuotedString(val, buffer, sizeof(buffer)));
VFS_WRITE(f, s, strlen(s));
}
}

View File

@ -42,7 +42,7 @@ packet header
The remote connection never knows if it missed a reliable message, the
local side detects that it has been dropped by seeing a sequence acknowledge
higher thatn the last reliable sequence, but without the correct evon/odd
higher thatn the last reliable sequence, but without the correct even/odd
bit for the reliable set.
If the sender notices that a reliable message has been dropped, it will be
@ -84,9 +84,10 @@ int net_drop;
cvar_t showpackets = SCVAR("showpackets", "0");
cvar_t showdrop = SCVAR("showdrop", "0");
cvar_t qport = SCVAR("qport", "0");
cvar_t net_mtu = CVARD("net_mtu", "1450", "Specifies a maximum udp payload size, above which packets will be fragmented. If routers all worked properly this could be some massive value, and some massive value may work really nicely for lans. Use smaller values than the default if you're connecting through nested tunnels through routers that fail with IP fragmentation.");
cvar_t net_mtu = CVARD("net_mtu", "1440", "Specifies a maximum udp payload size, above which packets will be fragmented. If routers all worked properly this could be some massive value, and some massive value may work really nicely for lans. Use smaller values than the default if you're connecting through nested tunnels through routers that fail with IP fragmentation.");
cvar_t pext_replacementdeltas = CVAR("pext_replacementdeltas", "1");
cvar_t pext_nqpredinfo = CVAR("debug_pext_nqpredinfo", "0");
/*returns the entire bitmask of supported+enabled extensions*/
unsigned int Net_PextMask(int maskset, qboolean fornq)
@ -196,7 +197,8 @@ unsigned int Net_PextMask(int maskset, qboolean fornq)
if (pext_replacementdeltas.ival)
mask |= PEXT2_REPLACEMENTDELTAS;
//mask |= PEXT2_PREDINFO;
if (fornq && pext_nqpredinfo.ival)
mask |= PEXT2_PREDINFO;
if (MAX_CLIENTS != QWMAX_CLIENTS)
mask |= PEXT2_MAXPLAYERS;
@ -206,6 +208,8 @@ unsigned int Net_PextMask(int maskset, qboolean fornq)
//only ones that are tested
mask &= PEXT2_VOICECHAT | PEXT2_REPLACEMENTDELTAS | PEXT2_PREDINFO;
}
else
mask &= ~PEXT2_PREDINFO;
}
return mask;
@ -221,6 +225,7 @@ void Netchan_Init (void)
{
int port;
Cvar_Register (&pext_nqpredinfo, "Protocol Extensions");
Cvar_Register (&pext_replacementdeltas, "Protocol Extensions");
Cvar_Register (&showpackets, "Networking");
Cvar_Register (&showdrop, "Networking");

View File

@ -118,7 +118,7 @@ int PM_PointContents (vec3_t p)
model_t *pm;
pm = pmove.physents[0].model;
if (!pm)
if (!pm || pm->needload)
return FTECONTENTS_EMPTY;
pc = pm->funcs.PointContents(pm, NULL, p);
//we need this for e2m2 - waterjumping on to plats wouldn't work otherwise.

View File

@ -75,7 +75,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PEXT2_SETANGLEDELTA 0x00000004
#define PEXT2_REPLACEMENTDELTAS 0x00000008
#define PEXT2_MAXPLAYERS 0x00000010 //Client is able to cope with more players than 32. abs max becomes 255, due to colormap issues.
#define PEXT2_PREDINFO 0x00000020 //movevars, NQ input sequences+acks.
#define PEXT2_PREDINFO 0x00000020 //movevar stats, NQ input sequences+acks.
//ZQuake transparent protocol extensions.
#define Z_EXT_PM_TYPE (1<<0) // basic PM_TYPE functionality (reliable jump_held)
@ -164,7 +164,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define svc_lightstyle 12 // [qbyte] [string]
#define svc_updatename 13 // [qbyte] [string]
#define svc_updatefrags 14 // [qbyte] [short]
#define svc_clientdata 15 // <shortbits + data>
#define svcnq_clientdata 15 // <shortbits + data>
#define svc_stopsound 16 // <see code>
#define svc_updatecolors 17 // [qbyte] [qbyte] [qbyte]
#define svc_particle 18 // [vec3] <variable>
@ -951,10 +951,12 @@ extern entity_state_t nullentitystate;
#define MAX_MVDPACKET_ENTITIES 196 // doesn't count nails
typedef struct
{
float servertime;
int num_entities;
int max_entities;
float servertime;
int num_entities;
int max_entities;
entity_state_t *entities;
qboolean fixangles[MAX_SPLITS];
vec3_t fixedangles[MAX_SPLITS];
} packet_entities_t;
typedef struct usercmd_s

View File

@ -551,7 +551,7 @@ void TL_ParseLanguage (char *name, char *data, int num) //this is one of the fir
break;
}
s = COM_ParseCString(s);
s = COM_ParseCString(s, com_token, sizeof(com_token));
if (i == STL_MAXSTL) //silently ignore - allow other servers or clients to add stuff
continue;

View File

@ -2369,7 +2369,7 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
VectorScale((m+8), mod->clampscale, (m+8));
}
if (e->flags & Q2RF_WEAPONMODEL && r_refdef.currentplayernum>=0)
if (e->flags & Q2RF_WEAPONMODEL)
{
/*FIXME: no bob*/
float iv[16];

View File

@ -60,17 +60,36 @@ extern cvar_t gl_picmip2d;
texid_t D3D9_AllocNewTexture(char *ident, int width, int height, unsigned int flags)
{
IDirect3DTexture9 *tx;
texid_t ret = r_nulltex;
if (!FAILED(IDirect3DDevice9_CreateTexture(pD3DDev9, width, height, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tx, NULL)))
ret.ptr = tx;
return ret;
/*unconditionally allocate a new texture*/
d3dtexture_t *tex = calloc(1, sizeof(*tex)+strlen(ident));
strcpy(tex->name, ident);
tex->tex.ptr = NULL;
tex->tex.ref = &tex->com;
tex->next = d3dtextures;
d3dtextures = tex;
if (!tex->tex.ptr)
{
if (!FAILED(IDirect3DDevice9_CreateTexture(pD3DDev9, width, height, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tx, NULL)))
tex->tex.ptr = tx;
}
return tex->tex;
}
void D3D9_DestroyTexture (texid_t tex)
{
IDirect3DTexture9 *tx = tex.ptr;
if (tx)
IDirect3DTexture9_Release(tx);
d3dtexture_t **link;
for (link = &d3dtextures; *link; link = &(*link)->next)
{
if (*link == (d3dtexture_t*)tex.ref)
{
*link = (*link)->next;
if (tex.ptr)
IDirect3DTexture9_Release((IDirect3DTexture9*)tex.ptr);
return;
}
}
}
static void D3D9_RoundDimensions(int *scaled_width, int *scaled_height, qboolean mipmap)

View File

@ -770,7 +770,6 @@ static qboolean D3D11_VID_Init(rendererstate_t *info, unsigned char *palette)
// pD3DX->lpVtbl->GetBufferSize((void*)pD3DX, &width, &height);
vid.pixelwidth = width;
vid.pixelheight = height;
vid.recalc_refdef = true;
vid.width = width;
vid.height = height;

View File

@ -1,17 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake", "ftequake.vcproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}"
ProjectSection(ProjectDependencies) = postProject
{0018E098-B12A-4E4D-9B22-6772DA287080} = {0018E098-B12A-4E4D-9B22-6772DA287080}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdlfte", "ftequake_SDL.vcproj", "{F384725A-62D4-4063-9941-6D8D2D6C2A47}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "npfte", "npfte.vcproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}"
ProjectSection(ProjectDependencies) = postProject
{0018E098-B12A-4E4D-9B22-6772DA287080} = {0018E098-B12A-4E4D-9B22-6772DA287080}
EndProjectSection
EndProject
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "FTEQuake", "..\setup\setup.vdproj", "{E0EE8B50-3A75-42A9-B80A-787675979B0C}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "botlib", "botlib.vcproj", "{0018E098-B12A-4E4D-9B22-6772DA287080}"
@ -38,6 +26,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fs_mpq", "..\..\plugins\mpq
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpserver", "..\http\httpserver.vcproj", "{E6BAD203-4704-4860-9C38-D4702E9CAD7D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake", "ftequake.vcproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}"
ProjectSection(ProjectDependencies) = postProject
{0018E098-B12A-4E4D-9B22-6772DA287080} = {0018E098-B12A-4E4D-9B22-6772DA287080}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dedserver", "dedserver.vcproj", "{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}"
ProjectSection(ProjectDependencies) = postProject
{0018E098-B12A-4E4D-9B22-6772DA287080} = {0018E098-B12A-4E4D-9B22-6772DA287080}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "npfte", "npfte.vcproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
D3DDebug|Win32 = D3DDebug|Win32
@ -66,114 +66,6 @@ Global
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.ActiveCfg = D3DDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.Build.0 = D3DDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|x64.ActiveCfg = D3DDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|x64.Build.0 = D3DDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DRelease|Win32.ActiveCfg = D3DRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DRelease|Win32.Build.0 = D3DRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DRelease|x64.ActiveCfg = D3DRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DRelease|x64.Build.0 = D3DRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|Win32.ActiveCfg = Debug Dedicated Server|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|Win32.Build.0 = Debug Dedicated Server|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|x64.ActiveCfg = Debug Dedicated Server|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|x64.Build.0 = Debug Dedicated Server|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug|Win32.ActiveCfg = MDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug|x64.ActiveCfg = D3DRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug|x64.Build.0 = D3DRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|Win32.Build.0 = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|x64.ActiveCfg = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|x64.Build.0 = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|Win32.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|Win32.Build.0 = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|x64.Build.0 = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|Win32.ActiveCfg = MDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|Win32.Build.0 = MDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|x64.ActiveCfg = MDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|x64.Build.0 = MDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|Win32.ActiveCfg = MinGLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|Win32.Build.0 = MinGLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|x64.ActiveCfg = MinGLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|x64.Build.0 = MinGLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|Win32.ActiveCfg = MinGLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|Win32.Build.0 = MinGLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|x64.ActiveCfg = MinGLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|x64.Build.0 = MinGLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|Win32.ActiveCfg = MRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|Win32.Build.0 = MRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|x64.ActiveCfg = MinGLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|x64.Build.0 = MinGLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|Win32.ActiveCfg = Release Dedicated Server|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|Win32.Build.0 = Release Dedicated Server|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|x64.Build.0 = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release|Win32.ActiveCfg = MRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release|Win32.Build.0 = MRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release|x64.Build.0 = GLRelease|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.D3DDebug|Win32.ActiveCfg = D3DRelease_SDL|Win32
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.D3DDebug|x64.ActiveCfg = D3DDebug_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.D3DRelease|Win32.ActiveCfg = D3DDebug_SDL|Win32
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.D3DRelease|x64.ActiveCfg = D3DDebug_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug Dedicated Server|Win32.ActiveCfg = Debug Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug Dedicated Server|x64.ActiveCfg = Debug Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug Dedicated Server|x64.Build.0 = Debug Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug|Win32.ActiveCfg = Debug Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug|x64.ActiveCfg = Debug Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Debug|x64.Build.0 = Debug Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.GLDebug|Win32.ActiveCfg = GLDebug_SDL|Win32
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.GLDebug|Win32.Build.0 = GLDebug_SDL|Win32
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.GLDebug|x64.ActiveCfg = GLDebug_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.GLRelease|Win32.ActiveCfg = GLRelease_SDL|Win32
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.GLRelease|Win32.Build.0 = GLRelease_SDL|Win32
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.GLRelease|x64.ActiveCfg = GLRelease_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.MDebug|Win32.ActiveCfg = MDebug_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.MDebug|x64.ActiveCfg = MDebug_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.MinGLDebug|Win32.ActiveCfg = MinGLDebug_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.MinGLDebug|x64.ActiveCfg = MinGLDebug_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.MinGLRelease|Win32.ActiveCfg = MinGLRelease_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.MinGLRelease|x64.ActiveCfg = MinGLRelease_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.MRelease|Win32.ActiveCfg = MRelease_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.MRelease|x64.ActiveCfg = MRelease_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release Dedicated Server|Win32.ActiveCfg = Release Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release Dedicated Server|x64.ActiveCfg = Release Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release Dedicated Server|x64.Build.0 = Release Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release|Win32.ActiveCfg = Release Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release|x64.ActiveCfg = Release Dedicated Server_SDL|x64
{F384725A-62D4-4063-9941-6D8D2D6C2A47}.Release|x64.Build.0 = Release Dedicated Server_SDL|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|Win32.Build.0 = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|x64.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DRelease|Win32.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DRelease|x64.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug Dedicated Server|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug Dedicated Server|Win32.Build.0 = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug Dedicated Server|x64.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug|Win32.Build.0 = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug|x64.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|x64.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLRelease|Win32.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLRelease|x64.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MDebug|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MDebug|x64.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLDebug|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLDebug|x64.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLRelease|Win32.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLRelease|Win32.Build.0 = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLRelease|x64.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MRelease|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MRelease|Win32.Build.0 = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MRelease|x64.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release Dedicated Server|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release Dedicated Server|Win32.Build.0 = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release Dedicated Server|x64.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release|Win32.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release|Win32.Build.0 = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release|x64.ActiveCfg = GLDebug|Win32
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DDebug|Win32.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DDebug|x64.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DRelease|Win32.ActiveCfg = Release
@ -551,6 +443,134 @@ Global
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.Release|Win32.ActiveCfg = Release|Win32
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.Release|Win32.Build.0 = Release|Win32
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.Release|x64.ActiveCfg = Release|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.ActiveCfg = D3DDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.Build.0 = D3DDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|x64.ActiveCfg = D3DDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|x64.Build.0 = D3DDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DRelease|Win32.ActiveCfg = D3DRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DRelease|Win32.Build.0 = D3DRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DRelease|x64.ActiveCfg = D3DRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DRelease|x64.Build.0 = D3DRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|Win32.ActiveCfg = Debug Dedicated Server|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|Win32.Build.0 = Debug Dedicated Server|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|x64.ActiveCfg = Debug Dedicated Server|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|x64.Build.0 = Debug Dedicated Server|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug|Win32.ActiveCfg = MDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug|Win32.Build.0 = MDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug|x64.ActiveCfg = MDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug|x64.Build.0 = MDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|Win32.Build.0 = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|x64.ActiveCfg = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|x64.Build.0 = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|Win32.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|Win32.Build.0 = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|x64.Build.0 = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|Win32.ActiveCfg = MDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|Win32.Build.0 = MDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|x64.ActiveCfg = MDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|x64.Build.0 = MDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|Win32.ActiveCfg = MinGLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|Win32.Build.0 = MinGLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|x64.ActiveCfg = MinGLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|x64.Build.0 = MinGLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|Win32.ActiveCfg = MinGLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|Win32.Build.0 = MinGLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|x64.ActiveCfg = MinGLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|x64.Build.0 = MinGLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|Win32.ActiveCfg = MRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|Win32.Build.0 = MRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|x64.ActiveCfg = MRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|x64.Build.0 = MRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|Win32.ActiveCfg = Release Dedicated Server|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|Win32.Build.0 = Release Dedicated Server|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|x64.ActiveCfg = Release Dedicated Server|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|x64.Build.0 = Release Dedicated Server|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release|Win32.ActiveCfg = D3DRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release|Win32.Build.0 = D3DRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release|x64.ActiveCfg = D3DRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release|x64.Build.0 = D3DRelease|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.D3DDebug|Win32.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.D3DDebug|x64.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.D3DDebug|x64.Build.0 = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.D3DRelease|Win32.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.D3DRelease|x64.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.D3DRelease|x64.Build.0 = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Debug Dedicated Server|Win32.ActiveCfg = Debug Dedicated Server|Win32
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Debug Dedicated Server|Win32.Build.0 = Debug Dedicated Server|Win32
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Debug Dedicated Server|x64.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Debug Dedicated Server|x64.Build.0 = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Debug|Win32.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Debug|x64.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Debug|x64.Build.0 = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.GLDebug|Win32.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.GLDebug|x64.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.GLDebug|x64.Build.0 = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.GLRelease|Win32.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.GLRelease|x64.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.GLRelease|x64.Build.0 = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.MDebug|Win32.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.MDebug|x64.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.MDebug|x64.Build.0 = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.MinGLDebug|Win32.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.MinGLDebug|x64.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.MinGLDebug|x64.Build.0 = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.MinGLRelease|Win32.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.MinGLRelease|x64.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.MinGLRelease|x64.Build.0 = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.MRelease|Win32.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.MRelease|x64.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.MRelease|x64.Build.0 = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Release Dedicated Server|Win32.ActiveCfg = Release Dedicated Server|Win32
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Release Dedicated Server|Win32.Build.0 = Release Dedicated Server|Win32
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Release Dedicated Server|x64.ActiveCfg = Release Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Release Dedicated Server|x64.Build.0 = Release Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Release|Win32.ActiveCfg = Release Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Release|x64.ActiveCfg = Release Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Release|x64.Build.0 = Release Dedicated Server|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|Win32.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|x64.Build.0 = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DRelease|Win32.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DRelease|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DRelease|x64.Build.0 = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug Dedicated Server|Win32.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug Dedicated Server|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug Dedicated Server|x64.Build.0 = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug|Win32.Build.0 = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug|x64.ActiveCfg = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Debug|x64.Build.0 = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|Win32.Build.0 = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|x64.ActiveCfg = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLDebug|x64.Build.0 = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLRelease|Win32.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLRelease|Win32.Build.0 = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLRelease|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.GLRelease|x64.Build.0 = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MDebug|Win32.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MDebug|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MDebug|x64.Build.0 = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLDebug|Win32.ActiveCfg = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLDebug|Win32.Build.0 = GLDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLDebug|x64.ActiveCfg = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLDebug|x64.Build.0 = GLDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLRelease|Win32.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLRelease|Win32.Build.0 = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLRelease|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MinGLRelease|x64.Build.0 = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MRelease|Win32.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MRelease|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.MRelease|x64.Build.0 = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release Dedicated Server|Win32.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release Dedicated Server|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release Dedicated Server|x64.Build.0 = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release|Win32.ActiveCfg = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release|Win32.Build.0 = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Release|x64.Build.0 = GLRelease|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -4062,7 +4062,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLR_DrawPortal(batch, cl.worldmodel->batches, 1);
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false);
qglViewport (0, 0, vid.pixelwidth, vid.pixelheight);
qglViewport (oprect.x, oprect.y - oprect.height, oprect.width, oprect.height);
r_refdef.vrect = orect;
r_refdef.pxrect = oprect;
}
@ -4116,7 +4116,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
GLR_DrawPortal(batch, cl.worldmodel->batches, ((batch->shader->flags & SHADER_HASREFRACTDEPTH)?3:2)); //fixme
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false);
qglViewport (0, 0, vid.pixelwidth, vid.pixelheight);
qglViewport (oprect.x, oprect.y - oprect.height, oprect.width, oprect.height);
r_refdef.vrect = ovrect;
r_refdef.pxrect = oprect;
}
@ -4157,7 +4157,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
r_refdef.recurse = false;
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false);
qglViewport (0, 0, vid.pixelwidth, vid.pixelheight);
qglViewport (oprect.x, oprect.height + oprect.y, oprect.width, oprect.height);
r_refdef.vrect = orect;
r_refdef.pxrect = oprect;
}

View File

@ -204,12 +204,20 @@ texid_t GL_AllocNewTexture(char *name, int w, int h, unsigned int flags)
void GL_DestroyTexture(texid_t tex)
{
gltexture_t **link;
if (!tex.ref)
return;
//FIXME: unlink the old one
qglDeleteTextures(1, &tex.num);
for (link = &gltextures; *link; link = &(*link)->next)
{
if (*link == (gltexture_t*)tex.ref)
{
Hash_RemoveData(&gltexturetable, (*link)->identifier, *link);
*link = (*link)->next;
qglDeleteTextures(1, &tex.num);
BZ_Free(tex.ref);
return;
}
}
}
//=============================================================================
@ -422,6 +430,8 @@ void GLDraw_FlushOldTextures(void)
t = *link;
if (t->com.regsequence != r_regsequence)
{
//make sure the hash table can't still find it...
Hash_RemoveData(&gltexturetable, t->identifier, t);
qglDeleteTextures(1, &t->texnum.num);
(*link)->next = t->next;
BZ_Free(t);

View File

@ -1305,6 +1305,7 @@ int Font_CharEndCoord(struct font_s *font, int x, unsigned int charcode)
}
//obtains the width of a character from a given font. This is how wide it is. The next char should be drawn at x + result.
//FIXME: this function cannot cope with tab and should not be used.
int Font_CharWidth(unsigned int charcode)
{
struct charcache_s *c;
@ -1324,6 +1325,7 @@ int Font_CharWidth(unsigned int charcode)
}
//obtains the width of a character from a given font. This is how wide it is. The next char should be drawn at x + result.
//FIXME: this function cannot cope with tab and should not be used.
float Font_CharScaleWidth(unsigned int charcode)
{
struct charcache_s *c;

View File

@ -102,7 +102,7 @@ void R_NetGraph (void)
lost = CL_CalcNet();
for (a=0 ; a<NET_TIMINGS ; a++)
{
i = (cls.netchan.outgoing_sequence-a) & NET_TIMINGSMASK;
i = (cl.movesequence-a) & NET_TIMINGSMASK;
R_LineGraph (NET_TIMINGS-1-a, packet_latency[i]);
}

View File

@ -18,7 +18,7 @@ BASE_CFLAGS=-ggdb $(USEGUI_CFLAGS)
BASE_LDFLAGS=-s
# set to "" for debugging
DO_CC=$(CC) $(BASE_CFLAGS) -o $@ -c $< $(CFLAGS)
DO_CC?=$(CC) $(BASE_CFLAGS) -o $@ -c $< $(CFLAGS)
lib:

View File

@ -4508,12 +4508,12 @@ void QCC_PR_EmitClassFromFunction(QCC_def_t *scope, QCC_type_t *basetype)
static QCC_def_t *QCC_PR_ExpandField(QCC_def_t *ent, QCC_def_t *field)
{
QCC_def_t *r, *tmp;
//FIXME: class.staticmember should directly read staticmember instead of trying to dereference
if (field->type->type == ev_variant || field->type->type != ev_field || !field->type->aux_type)
{
if (field->type->type != ev_variant)
{
QCC_PR_ParseWarning(ERR_INTERNAL, "QCC_PR_ExpandField: invalid field type");
QCC_PR_ParsePrintDef(ERR_INTERNAL, field);
QCC_PR_ParseErrorPrintDef(ERR_INTERNAL, field, "QCC_PR_ExpandField: invalid field type");
}
r = QCC_PR_Statement(&pr_opcodes[OP_LOAD_V], ent, field, NULL);
tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t));
@ -4530,8 +4530,8 @@ static QCC_def_t *QCC_PR_ExpandField(QCC_def_t *ent, QCC_def_t *field)
switch(field->type->aux_type->type)
{
default:
QCC_PR_ParseWarning(ERR_INTERNAL, "QCC_PR_ExpandField: invalid field type");
QCC_PR_ParsePrintDef(ERR_INTERNAL, field);
QCC_PR_ParseErrorPrintDef(ERR_INTERNAL, field, "QCC_PR_ExpandField: invalid field type");
r = field;
break;
case ev_integer:
r = QCC_PR_Statement(&pr_opcodes[OP_LOAD_I], ent, field, NULL);

View File

@ -67,7 +67,7 @@ static char demomsgbuf[MAX_OVERALLMSGLEN];
mvddest_t *singledest;
mvddest_t *SV_InitStream(int socket);
static qboolean SV_MVD_Record (mvddest_t *dest);
qboolean SV_MVD_Record (mvddest_t *dest);
char *SV_MVDName2Txt(char *name);
extern cvar_t qtv_password;
@ -1586,7 +1586,7 @@ void SV_WriteSetMVDMessage (void)
}
void SV_MVD_SendInitialGamestate(mvddest_t *dest);
static qboolean SV_MVD_Record (mvddest_t *dest)
qboolean SV_MVD_Record (mvddest_t *dest)
{
if (!dest)
return false;
@ -2264,7 +2264,14 @@ void SV_MVDEasyRecord_f (void)
else
{
i = Dem_CountPlayers();
if (teamplay.value >= 1 && i > 2)
/*if (!deathmatch.ival)
{
if (coop.ival || i>1)
snprintf (name, sizeof(name), "coop_%s_%d(%d)", sv.name, skill.ival, i);
else
snprintf (name, sizeof(name), "sp_%s_%d_%s", sv.name, skill.ival, Dem_PlayerName(0));
}
else*/ if (teamplay.value >= 1 && i > 2)
{
// Teamplay
snprintf (name, sizeof(name), "%don%d_", Dem_CountTeamPlayers(Dem_Team(1)), Dem_CountTeamPlayers(Dem_Team(2)));

View File

@ -1240,6 +1240,9 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
// Con_Printf("%f\n", sv.world.physicstime);
}
//predinfo extension reworks stats, making svc_clientdata redundant.
if (client->fteprotocolextensions2 & PEXT2_PREDINFO)
return;
bits = 0;
@ -1327,7 +1330,7 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
// send the data
MSG_WriteByte (msg, svc_clientdata);
MSG_WriteByte (msg, svcnq_clientdata);
MSG_WriteShort (msg, bits);
if (bits & SU_EXTEND1)
@ -1627,16 +1630,13 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
else
statsi[STAT_VIEWZOOM] = ent->xv->viewzoom*255;
if (client->fteprotocolextensions2 & PEXT2_PREDINFO)
if (client->protocol == SCP_DARKPLACES7 || (client->fteprotocolextensions2 & PEXT2_PREDINFO))
{
statsf[STAT_MOVEVARS_GRAVITY] = sv_gravity.value;
statsf[STAT_MOVEVARS_ENTGRAVITY] = host_client->entgravity;
statsf[STAT_MOVEVARS_MAXSPEED] = host_client->maxspeed;
}
if (client->protocol == SCP_DARKPLACES7)
{
/*note: statsf is truncated, which would mess things up*/
float *statsfi = (float*)statsi;
float *statsfi;
if (client->fteprotocolextensions2 & PEXT2_PREDINFO)
statsfi = statsf;
else
statsfi = (float*)statsi; /*dp requires a union of ints and floats, which is rather hideous...*/
// statsfi[STAT_MOVEVARS_WALLFRICTION] = sv_wall
statsfi[STAT_MOVEVARS_FRICTION] = sv_friction.value;
statsfi[STAT_MOVEVARS_WATERFRICTION] = sv_waterfriction.value;
@ -1649,7 +1649,7 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
statsfi[STAT_MOVEVARS_ACCELERATE] = sv_accelerate.value;
statsfi[STAT_MOVEVARS_AIRACCELERATE] = sv_airaccelerate.value;
statsfi[STAT_MOVEVARS_WATERACCELERATE] = sv_wateraccelerate.value;
statsfi[STAT_MOVEVARS_ENTGRAVITY] = host_client->entgravity;
statsfi[STAT_MOVEVARS_ENTGRAVITY] = host_client->entgravity/sv_gravity.value;
statsfi[STAT_MOVEVARS_JUMPVELOCITY] = 270;//sv_jumpvelocity.value; //bah
statsfi[STAT_MOVEVARS_EDGEFRICTION] = sv_edgefriction.value;
statsfi[STAT_MOVEVARS_MAXAIRSPEED] = host_client->maxspeed;

View File

@ -393,6 +393,7 @@ static qintptr_t AVDec_Shutdown(qintptr_t *args)
static media_decoder_funcs_t decoderfuncs =
{
"avplug",
AVDec_Create,
AVDec_DisplayFrame,
NULL,//doneframe
@ -429,7 +430,10 @@ qintptr_t Plug_Init(qintptr_t *args)
okay |= AVDec_Init();
okay |= AVEnc_Init();
if (okay)
{
av_register_all();
avcodec_register_all();
}
return okay;
}

View File

@ -290,7 +290,7 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height
audiocodec = avcodec_find_encoder_by_name(codecname);
if (!audiocodec)
{
Con_Printf("Unsupported avplug_codec \"%s\"\n", codecname);
Con_Printf("avplug: Unsupported avplug_codec \"%s\"\n", codecname);
return NULL;
}
}
@ -299,19 +299,19 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height
}
}
Con_DPrintf("Using format \"%s\"\n", fmt->name);
Con_DPrintf("avplug: Using format \"%s\"\n", fmt->name);
if (videocodec)
Con_DPrintf("Using Video Codec \"%s\"\n", videocodec->name);
Con_DPrintf("avplug: Using Video Codec \"%s\"\n", videocodec->name);
else
Con_DPrintf("Not encoding video\n");
Con_DPrintf("avplug: Not encoding video\n");
if (audiocodec)
Con_DPrintf("Using Audio Codec \"%s\"\n", audiocodec->name);
Con_DPrintf("avplug: Using Audio Codec \"%s\"\n", audiocodec->name);
else
Con_DPrintf("Not encoding audio\n");
Con_DPrintf("avplug: Not encoding audio\n");
if (!videocodec && !audiocodec)
{
Con_DPrintf("Nothing to encode!\n");
Con_DPrintf("avplug: Nothing to encode!\n");
return NULL;
}
@ -339,7 +339,7 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height
AVCodecContext *c = ctx->video_st->codec;
if (avcodec_open2(c, videocodec, NULL) < 0)
{
Con_Printf("Could not init codec instance \"%s\". Maybe try a different framerate/resolution/bitrate\n", videocodec->name);
Con_Printf("avplug: Could not init codec instance \"%s\". Maybe try a different framerate/resolution/bitrate\n", videocodec->name);
AVEnc_End(ctx);
return NULL;
}
@ -360,7 +360,7 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height
AVCodecContext *c = ctx->audio_st->codec;
if (avcodec_open2(c, audiocodec, NULL) < 0)
{
Con_Printf("Could not init codec instance \"%s\".\n", audiocodec->name);
Con_Printf("avplug: Could not init codec instance \"%s\".\n", audiocodec->name);
AVEnc_End(ctx);
return NULL;
}
@ -406,6 +406,7 @@ static void AVEnc_End (void *vctx)
}
static media_encoder_funcs_t encoderfuncs =
{
"avplug",
AVEnc_Begin,
AVEnc_Video,
AVEnc_Audio,
@ -438,15 +439,15 @@ menutext 0 24 "Cancel"
qboolean AVEnc_Init(void)
{
pCvar_Register("avplug_format", "", 0, "avplug");
pCvar_Register("avplug_format", "mp4", 0, "avplug");
pCvar_Register("avplug_videocodec", "", 0, "avplug");
pCvar_Register("avplug_videocodecprofile", "", 0, "avplug");
pCvar_Register("avplug_videobitrate", "4000000", 0, "avplug");
pCvar_Register("avplug_videoforcewidth", "", 0, "avplug");
pCvar_Register("avplug_videoforceheight", "", 0, "avplug");
pCvar_Register("avplug_audiocodec", "", 0, "avplug");
pCvar_Register("avplug_audiobitrate", "64000", 0, "avplug");
pCvar_Register("avplug_videocodec", "mpeg4", 0, "avplug");
pCvar_Register("avplug_videocodecprofile", "", 0, "avplug");
pCvar_Register("avplug_videobitrate", "4000000", 0, "avplug");
pCvar_Register("avplug_videoforcewidth", "", 0, "avplug");
pCvar_Register("avplug_videoforceheight", "", 0, "avplug");
pCvar_Register("avplug_audiocodec", "libmp3lame", 0, "avplug");
pCvar_Register("avplug_audiobitrate", "64000", 0, "avplug");
if (!pPlug_ExportNative("Media_VideoEncoder", &encoderfuncs))
{

221
plugins/mpq/fs_mpq.vcproj Normal file
View File

@ -0,0 +1,221 @@
<?xml version="1.0" encoding="UTF-8"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="fs_mpq"
ProjectGUID="{72269FEE-293D-40BC-A7AE-E429F4496869}"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../engine/server;../../engine/gl;../../engine/qclib;../../engine/client;../../engine/common"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;FTEPLUGIN"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="zlib.lib"
OutputFile="../../fteplug_mpqx86.dll"
LinkIncremental="2"
AdditionalLibraryDirectories="../..\engine\libs"
ModuleDefinitionFile="../plugin.def"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../engine/server;../../engine/gl;../../engine/qclib;../../engine/client;../../engine/common"
PreprocessorDefinitions="WIN32;FTEPLUGIN"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="zlib.lib"
LinkIncremental="2"
AdditionalLibraryDirectories="../..\engine\libs"
ModuleDefinitionFile="../plugin.def"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\blast.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\blast.c"
>
</File>
<File
RelativePath=".\fs_mpq.c"
>
</File>
<File
RelativePath="..\plugin.c"
>
</File>
<File
RelativePath="..\plugin.def"
>
</File>
<File
RelativePath="..\qvm_api.c"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>