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 \ huffman.o \
mymad.o mymad.o
PROGS_OBJS = \ QCC_OBJS= \
comprout.o \ comprout.o \
hash.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 \ initlib.o \
pr_bgcmd.o \ pr_bgcmd.o \
pr_skelobj.o \ pr_skelobj.o \
@ -528,12 +535,7 @@ PROGS_OBJS = \
pr_exec.o \ pr_exec.o \
pr_multi.o \ pr_multi.o \
pr_x86.o \ pr_x86.o \
qcc_cmdlib.o \ qcdecomp.o
qccmain.o \
qcc_pr_comp.o \
qcc_pr_lex.o \
qcdecomp.o \
qcd_main.o
SERVER_OBJS = \ SERVER_OBJS = \
pr_cmds.o \ 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 .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 ifdef windir
debugdir: debugdir:
@-mkdir -p $(subst /,\, $(OUT_DIR)) @-mkdir -p $(subst /,\, $(OUT_DIR))

View file

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

View file

@ -431,7 +431,7 @@ typedef struct botlib_export_s
} botlib_export_t; } botlib_export_t;
//linking of bot library //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: /* Library variables:

View file

@ -92,6 +92,10 @@ void CL_WriteDemoCmd (usercmd_t *pcmd)
qbyte c; qbyte c;
q1usercmd_t cmd; 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); //Con_Printf("write: %ld bytes, %4.4f\n", msg->cursize, demtime);
fl = LittleFloat((float)demtime); fl = LittleFloat((float)demtime);
@ -131,7 +135,7 @@ CL_WriteDemoMessage
Dumps the current net message, prefixed by the length and view angles 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 len;
int i; int i;
@ -140,37 +144,50 @@ void CL_WriteDemoMessage (sizebuf_t *msg)
//Con_Printf("write: %ld bytes, %4.4f\n", msg->cursize, demtime); //Con_Printf("write: %ld bytes, %4.4f\n", msg->cursize, demtime);
if (!cls.demorecording) switch (cls.demorecording)
{
case 0:
return; return;
case 1: //QW
fl = LittleFloat((float)demtime);
VFS_WRITE (cls.demooutfile, &fl, sizeof(fl));
fl = LittleFloat((float)demtime); c = dem_read;
VFS_WRITE (cls.demooutfile, &fl, sizeof(fl)); VFS_WRITE (cls.demooutfile, &c, sizeof(c));
c = dem_read; if (*(int*)msg->data == -1)
VFS_WRITE (cls.demooutfile, &c, sizeof(c)); {
//connectionless packet.
if (*(int*)msg->data == -1) len = LittleLong (msg->cursize);
{ VFS_WRITE (cls.demooutfile, &len, 4);
//connectionless packet. VFS_WRITE (cls.demooutfile, msg->data + msg_readcount, msg->cursize - msg_readcount);
len = LittleLong (msg->cursize); }
VFS_WRITE (cls.demooutfile, &len, 4); else
VFS_WRITE (cls.demooutfile, msg->data + msg_readcount, msg->cursize - msg_readcount); {
//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); VFS_FLUSH (cls.demooutfile);
} }
@ -244,6 +261,8 @@ int readdemobytes(int *readpos, void *data, int len)
{ {
int i; int i;
int trybytes; 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. 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 olddemotime = 0;
float nextdemotime = 0; float nextdemotime = 0;
qboolean CL_GetDemoMessage (void) 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 ((cls.timedemo && host_framecount == demoframe) || (!cls.timedemo && demtime<= cl.gametime && cl.gametime))// > dem_lasttime+demtime)
{ {
if (demtime <= cl.gametime-1) if (demtime <= cl.gametime-1)
{
demtime = cl.gametime; 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; return 0;
} }
demoframe = host_framecount; demoframe = host_framecount;
@ -487,13 +487,11 @@ qboolean CL_GetDemoMessage (void)
} }
if (cls.demoplayback == DPB_NETQUAKE) if (cls.demoplayback == DPB_NETQUAKE)
{ {
VectorCopy (cl.playerview[1].viewangles, cl.playerview[2].viewangles);
for (i=0 ; i<3 ; i++) for (i=0 ; i<3 ; i++)
{ {
readdemobytes(&demopos, &f, 4); 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; olddemotime = demtime;
@ -645,42 +643,6 @@ readnext:
Con_Printf("mvd demos/qtv streams should not contain dem_cmd\n"); Con_Printf("mvd demos/qtv streams should not contain dem_cmd\n");
olddemotime = demtime+1; olddemotime = demtime+1;
CL_StopPlayback (); 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; return 0;
} }
else else
@ -715,6 +677,7 @@ readnext:
for (i=0 ; i<3 ; i++) for (i=0 ; i<3 ; i++)
{ {
readdemobytes (&demopos, &f, 4); readdemobytes (&demopos, &f, 4);
demoangles[i] = LittleFloat (f);
cl.playerview[0].viewangles[i] = LittleFloat (f); cl.playerview[0].viewangles[i] = LittleFloat (f);
} }
goto readnext; goto readnext;
@ -880,8 +843,9 @@ void CL_Stop_f (void)
{ {
#ifndef CLIENTONLY #ifndef CLIENTONLY
SV_MVDStop_f(); SV_MVDStop_f();
#endif #else
Con_Printf ("Not recording a demo.\n"); Con_Printf ("Not recording a demo.\n");
#endif
return; return;
} }
@ -890,7 +854,7 @@ void CL_Stop_f (void)
MSG_WriteLong (&net_message, -1); // -1 sequence means out of band MSG_WriteLong (&net_message, -1); // -1 sequence means out of band
MSG_WriteByte (&net_message, svc_disconnect); MSG_WriteByte (&net_message, svc_disconnect);
MSG_WriteString (&net_message, "EndOfDemo"); MSG_WriteString (&net_message, "EndOfDemo");
CL_WriteDemoMessage (&net_message); CL_WriteDemoMessage (&net_message, sizeof(int));
// finish up // finish up
VFS_CLOSE (cls.demooutfile); VFS_CLOSE (cls.demooutfile);
@ -946,7 +910,7 @@ void CL_WriteSetDemoMessage (void)
//Con_Printf("write: %ld bytes, %4.4f\n", msg->cursize, demtime); //Con_Printf("write: %ld bytes, %4.4f\n", msg->cursize, demtime);
if (!cls.demorecording) if (cls.demorecording != 1)
return; return;
fl = LittleFloat((float)demtime); 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(); c = Cmd_Argc();
if (c > 2) if (c > 2)
{ {
#ifndef CLIENTONLY
CL_RecordMap_f();
#endif
Con_Printf ("record <demoname>\n"); Con_Printf ("record <demoname>\n");
return; return;
} }
@ -1110,199 +1122,172 @@ void CL_Record_f (void)
/*-------------------------------------------------*/ /*-------------------------------------------------*/
// serverdata switch(cls.protocol)
// send the info about the new client to all connected clients {
memset(&buf, 0, sizeof(buf)); case CP_QUAKEWORLD:
buf.data = buf_data;
buf.maxsize = sizeof(buf_data);
buf.prim = cls.netchan.netprim;
// send the serverdata // serverdata
MSG_WriteByte (&buf, svc_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 #ifdef PROTOCOL_VERSION_FTE
if (cls.fteprotocolextensions) //maintain demo compatability if (cls.fteprotocolextensions) //maintain demo compatability
{ {
MSG_WriteLong (&buf, PROTOCOL_VERSION_FTE); MSG_WriteLong (&buf, PROTOCOL_VERSION_FTE);
MSG_WriteLong (&buf, cls.fteprotocolextensions); MSG_WriteLong (&buf, cls.fteprotocolextensions);
} }
if (cls.fteprotocolextensions2) //maintain demo compatability if (cls.fteprotocolextensions2) //maintain demo compatability
{ {
MSG_WriteLong (&buf, PROTOCOL_VERSION_FTE2); MSG_WriteLong (&buf, PROTOCOL_VERSION_FTE2);
MSG_WriteLong (&buf, cls.fteprotocolextensions2); MSG_WriteLong (&buf, cls.fteprotocolextensions2);
} }
#endif #endif
MSG_WriteLong (&buf, PROTOCOL_VERSION_QW); MSG_WriteLong (&buf, PROTOCOL_VERSION_QW);
MSG_WriteLong (&buf, cl.servercount); MSG_WriteLong (&buf, cl.servercount);
MSG_WriteString (&buf, gamedirfile); MSG_WriteString (&buf, gamedirfile);
if (cls.fteprotocolextensions2 & PEXT2_MAXPLAYERS) 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++)
{ {
MSG_WriteByte (&buf, cl.playerview[i].playernum); MSG_WriteByte (&buf, cl.allocated_client_slots);
} MSG_WriteByte (&buf, cl.splitclients | (cl.spectator?128:0));
} for (i = 0; i < cl.splitclients; i++)
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); 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 // send full levelname
MSG_WriteString (&buf, cl.levelname); MSG_WriteString (&buf, cl.levelname);
// send the movevars // send the movevars
MSG_WriteFloat(&buf, movevars.gravity); MSG_WriteFloat(&buf, movevars.gravity);
MSG_WriteFloat(&buf, movevars.stopspeed); MSG_WriteFloat(&buf, movevars.stopspeed);
MSG_WriteFloat(&buf, movevars.maxspeed); MSG_WriteFloat(&buf, movevars.maxspeed);
MSG_WriteFloat(&buf, movevars.spectatormaxspeed); MSG_WriteFloat(&buf, movevars.spectatormaxspeed);
MSG_WriteFloat(&buf, movevars.accelerate); MSG_WriteFloat(&buf, movevars.accelerate);
MSG_WriteFloat(&buf, movevars.airaccelerate); MSG_WriteFloat(&buf, movevars.airaccelerate);
MSG_WriteFloat(&buf, movevars.wateraccelerate); MSG_WriteFloat(&buf, movevars.wateraccelerate);
MSG_WriteFloat(&buf, movevars.friction); MSG_WriteFloat(&buf, movevars.friction);
MSG_WriteFloat(&buf, movevars.waterfriction); MSG_WriteFloat(&buf, movevars.waterfriction);
MSG_WriteFloat(&buf, movevars.entgravity); MSG_WriteFloat(&buf, movevars.entgravity);
// send server info string // send server info string
MSG_WriteByte (&buf, svc_stufftext); MSG_WriteByte (&buf, svc_stufftext);
MSG_WriteString (&buf, va("fullserverinfo \"%s\"\n", cl.serverinfo) ); MSG_WriteString (&buf, va("fullserverinfo \"%s\"\n", cl.serverinfo) );
// send music (delayed) // send music (delayed)
MSG_WriteByte (&buf, svc_cdtrack); MSG_WriteByte (&buf, svc_cdtrack);
MSG_WriteByte (&buf, 0); // none in demos MSG_WriteByte (&buf, 0); // none in demos
#ifdef PEXT_SETVIEW #ifdef PEXT_SETVIEW
if (cl.playerview[0].viewentity != cl.playerview[0].playernum+1) //tell the player if we have a different view entity 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_WriteByte (&buf, svc_setview);
MSG_WriteEntity (&buf, cl.playerview[0].viewentity); MSG_WriteEntity (&buf, cl.playerview[0].viewentity);
} }
#endif #endif
// flush packet // flush packet
CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf); SZ_Clear (&buf);
// soundlist // soundlist
MSG_WriteByte (&buf, svc_soundlist); MSG_WriteByte (&buf, svc_soundlist);
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
n = 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++;
s = cl.sound_name[n+1]; s = cl.sound_name[n+1];
} while (*s)
if (buf.cursize) {
{ MSG_WriteString (&buf, s);
MSG_WriteByte (&buf, 0); if (buf.cursize > MAX_QWMSGLEN/2)
MSG_WriteByte (&buf, 0); {
CL_WriteRecordDemoMessage (&buf, seq++); MSG_WriteByte (&buf, 0);
SZ_Clear (&buf); MSG_WriteByte (&buf, n);
} CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
// modellist MSG_WriteByte (&buf, svc_soundlist);
MSG_WriteByte (&buf, svc_modellist); MSG_WriteByte (&buf, n + 1);
MSG_WriteByte (&buf, 0); }
n++;
n = 0; s = cl.sound_name[n+1];
s = cl.model_name[n+1]; }
while (*s) if (buf.cursize)
{
MSG_WriteString (&buf, s);
if (buf.cursize > MAX_QWMSGLEN/2)
{ {
MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, n); MSG_WriteByte (&buf, 0);
CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf); 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]; s = cl.model_name[n+1];
} while (*s)
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++)
{ {
MSG_WriteCoord (&buf, ent->origin[j]); MSG_WriteString (&buf, s);
MSG_WriteAngle (&buf, ent->angles[j]); 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)
if (buf.cursize > MAX_QWMSGLEN/2)
{ {
MSG_WriteByte (&buf, 0);
MSG_WriteByte (&buf, 0);
CL_WriteRecordDemoMessage (&buf, seq++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf); SZ_Clear (&buf);
} }
}
// spawnstaticsound // spawnstatic
// static sounds are skipped in demos, life is hard
// baselines for (i = 0; i < cl.num_statics; i++)
for (i = 0; i < cl_baselines_count; i++)
{
es = cl_baselines + i;
if (memcmp(es, &nullentitystate, sizeof(nullentitystate)))
{ {
MSG_WriteByte (&buf,svc_spawnbaseline); ent = &cl_static_entities[i].ent;
MSG_WriteEntity (&buf, i);
MSG_WriteByte (&buf, es->modelindex); MSG_WriteByte (&buf, svc_spawnstatic);
MSG_WriteByte (&buf, es->frame);
MSG_WriteByte (&buf, es->colormap); for (j = 1; j < MAX_MODELS; j++)
MSG_WriteByte (&buf, es->skinnum); 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++) for (j=0 ; j<3 ; j++)
{ {
MSG_WriteCoord(&buf, es->origin[j]); MSG_WriteCoord (&buf, ent->origin[j]);
MSG_WriteAngle(&buf, es->angles[j]); MSG_WriteAngle (&buf, ent->angles[j]);
} }
if (buf.cursize > MAX_QWMSGLEN/2) if (buf.cursize > MAX_QWMSGLEN/2)
@ -1311,114 +1296,151 @@ void CL_Record_f (void)
SZ_Clear (&buf); SZ_Clear (&buf);
} }
} }
}
MSG_WriteByte (&buf, svc_stufftext); // spawnstaticsound
MSG_WriteString (&buf, va("cmd spawn %i\n", cl.servercount) ); // static sounds are skipped in demos, life is hard
if (buf.cursize) // baselines
{
CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf);
}
// send current status of all other players for (i = 0; i < cl_baselines_count; i++)
for (i = 0; i < cl.allocated_client_slots; i++)
{
player = cl.players + i;
if (player->frags != 0)
{ {
MSG_WriteByte (&buf, svc_updatefrags); es = cl_baselines + i;
MSG_WriteByte (&buf, i);
MSG_WriteShort (&buf, player->frags); 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_stufftext);
{ MSG_WriteString (&buf, va("cmd spawn %i\n", cl.servercount) );
MSG_WriteByte (&buf, svc_updateping);
MSG_WriteByte (&buf, i);
MSG_WriteShort (&buf, player->ping);
}
if (player->pl != 0) if (buf.cursize)
{
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++); CL_WriteRecordDemoMessage (&buf, seq++);
SZ_Clear (&buf); SZ_Clear (&buf);
} }
}
// send all current light styles // send current status of all other players
for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
{ for (i = 0; i < cl.allocated_client_slots; i++)
if (i >= MAX_STANDARDLIGHTSTYLES) {
if (!*cl_lightstyle[i].map) player = cl.players + i;
continue;
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 #ifdef PEXT_LIGHTSTYLECOL
if ((cls.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && cl_lightstyle[i].colour!=7 && *cl_lightstyle[i].map) if ((cls.fteprotocolextensions & PEXT_LIGHTSTYLECOL) && cl_lightstyle[i].colour!=7 && *cl_lightstyle[i].map)
{ {
MSG_WriteByte (&buf, svcfte_lightstylecol); MSG_WriteByte (&buf, svcfte_lightstylecol);
MSG_WriteByte (&buf, (unsigned char)i); MSG_WriteByte (&buf, (unsigned char)i);
MSG_WriteByte (&buf, cl_lightstyle[i].colour); MSG_WriteByte (&buf, cl_lightstyle[i].colour);
MSG_WriteString (&buf, cl_lightstyle[i].map); MSG_WriteString (&buf, cl_lightstyle[i].map);
} }
else else
#endif #endif
{ {
MSG_WriteByte (&buf, svc_lightstyle); MSG_WriteByte (&buf, svc_lightstyle);
MSG_WriteByte (&buf, (unsigned char)i); MSG_WriteByte (&buf, (unsigned char)i);
MSG_WriteString (&buf, cl_lightstyle[i].map); MSG_WriteString (&buf, cl_lightstyle[i].map);
}
} }
}
for (i = ((cls.fteprotocolextensions&PEXT_HEXEN2)?MAX_QW_STATS:MAX_CL_STATS); i >= 0; i--) 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)
{ {
CL_WriteRecordDemoMessage (&buf, seq++); if (!cl.playerview[0].stats[i])
SZ_Clear (&buf); 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); static void CL_LerpNetFrameState(int fsanim, framestate_t *fs, lerpents_t *le);
qboolean CL_PredictPlayer(lerpents_t *le, entity_state_t *state, int sequence); 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_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; 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) else if (cls.protocol == CP_NETQUAKE)
{ {
int i; int i;
for (i = 0; i < MAX_SPLITS; i++) if (cls.demoplayback)
cl.playerview[i].fixangle = false; cls.netchan.incoming_unreliable++; //demo playback has no sequence info...
cls.netchan.incoming_sequence = cls.netchan.incoming_unreliable; cls.netchan.incoming_sequence = cls.netchan.incoming_unreliable;
cl.last_servermessage = realtime; cl.last_servermessage = realtime;
if (cls.fteprotocolextensions2 & PEXT2_PREDINFO) if (cls.fteprotocolextensions2 & PEXT2_PREDINFO)
@ -753,6 +754,18 @@ void CLFTE_ParseEntities(void)
cl.inframes[cls.netchan.incoming_sequence&UPDATE_MASK].receivedtime = realtime; 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) // if (cl.validsequence != cls.netchan.incoming_sequence-1)
// Con_Printf("CLIENT: Dropped a frame\n"); // Con_Printf("CLIENT: Dropped a frame\n");
} }
@ -885,13 +898,15 @@ void CLFTE_ParseEntities(void)
{ {
cl.oldvalidsequence = cl.validsequence; cl.oldvalidsequence = cl.validsequence;
cl.validsequence = cls.netchan.incoming_sequence; cl.validsequence = cls.netchan.incoming_sequence;
cl.ackedmovesequence = inputframe; CL_AckedInputFrame(inputframe, true);
cl.inframes[newpacket].invalid = false; cl.inframes[newpacket].invalid = false;
} }
else else
{ {
newp->num_entities = 0; newp->num_entities = 0;
cl.validsequence = 0; cl.validsequence = 0;
CL_AckedInputFrame(inputframe, false);
} }
} }
@ -978,9 +993,10 @@ void CLQW_ParsePacketEntities (qboolean delta)
full = true; full = true;
} }
//FIXME
cl.oldvalidsequence = cl.validsequence; cl.oldvalidsequence = cl.validsequence;
cl.validsequence = cls.netchan.incoming_sequence; cl.validsequence = cls.netchan.incoming_sequence;
cl.ackedmovesequence = cl.validsequence; CL_AckedInputFrame(cls.netchan.incoming_sequence, true);
oldindex = 0; oldindex = 0;
newindex = 0; newindex = 0;
@ -1293,12 +1309,14 @@ void CLDP_ParseDarkPlaces5Entities(void) //the things I do.. :o(
int oldi, newi, lowesti, lowestv, newremaining; int oldi, newi, lowesti, lowestv, newremaining;
qboolean remove; qboolean remove;
//server->client sequence
if (cl.numackframes == sizeof(cl.ackframes)/sizeof(cl.ackframes[0])) if (cl.numackframes == sizeof(cl.ackframes)/sizeof(cl.ackframes[0]))
cl.numackframes--; cl.numackframes--;
cl.ackframes[cl.numackframes++] = MSG_ReadLong(); /*server sequence to be acked*/ cl.ackframes[cl.numackframes++] = MSG_ReadLong(); /*server sequence to be acked*/
//client->server sequence ack
if (cls.protocol_nq >= CPNQ_DP7) 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; cl.inframes[(cls.netchan.incoming_sequence)&UPDATE_MASK].receivedtime = realtime;
pack = &cl.inframes[(cls.netchan.incoming_sequence)&UPDATE_MASK].packet_entities; 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. 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; lerpents_t *le;
entity_state_t *snew, *sold; entity_state_t *snew, *sold;
@ -2724,7 +2742,6 @@ static void CL_TransitionPacketEntities(int newsequence, packet_entities_t *newp
float a1, a2; float a1, a2;
float frac;
/* /*
seeing as how dropped packets cannot be filled in due to the reliable networking stuff, seeing as how dropped packets cannot be filled in due to the reliable networking stuff,
We can simply detect changes and lerp towards them 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 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. //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; cl.lerpentssequence = newsequence;
oldpnum=0; oldpnum=0;
@ -2953,7 +2965,7 @@ void CL_TransitionEntities (void)
packet_entities_t *packnew, *packold; packet_entities_t *packnew, *packold;
int newf, newff, oldf; int newf, newff, oldf;
qboolean nolerp; qboolean nolerp;
float servertime; float servertime, frac;
if (cls.protocol == CP_QUAKEWORLD && (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)) 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*/ /*transition the ents and stuff*/
packnew = &cl.inframes[newf].packet_entities; packnew = &cl.inframes[newf].packet_entities;
packold = &cl.inframes[oldf].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); // 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.currentpacktime = servertime;
cl.currentpackentities = packnew; cl.currentpackentities = packnew;
cl.previouspackentities = packold;
/*and transition players too*/ /*and transition players too*/
@ -2998,7 +3016,7 @@ void CL_TransitionEntities (void)
vec3_t move; vec3_t move;
lerpents_t *le; lerpents_t *le;
player_state_t *pnew, *pold; 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 = newff = oldf = cl.parsecount;
newf&=UPDATE_MASK; 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; player_state_t exact;
msec += cls.latency*1000; msec += cls.latency*1000;
@ -4316,7 +4334,7 @@ void CL_LinkPlayers (void)
if (pnum < cl.splitclients) if (pnum < cl.splitclients)
{ //this is a local player { //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]; lerpents_t *le = &cl.lerpplayers[j];
VectorCopy (le->origin, ent->origin); VectorCopy (le->origin, ent->origin);

View file

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

View file

@ -630,10 +630,13 @@ void CL_CheckForResend (void)
char data[2048]; char data[2048];
double t1, t2; double t1, t2;
int contype = 0; int contype = 0;
unsigned int pext1, pext2;
#ifndef CLIENTONLY #ifndef CLIENTONLY
if (!cls.state && sv.state) if (!cls.state && sv.state)
{ {
pext1 = 0;
pext2 = 0;
Q_strncpyz (cls.servername, "internalserver", sizeof(cls.servername)); Q_strncpyz (cls.servername, "internalserver", sizeof(cls.servername));
Cvar_ForceSet(&cl_servername, cls.servername); Cvar_ForceSet(&cl_servername, cls.servername);
@ -642,17 +645,27 @@ void CL_CheckForResend (void)
{ {
#ifdef Q3CLIENT #ifdef Q3CLIENT
case GT_QUAKE3: case GT_QUAKE3:
pext1 = 0;
pext2 = 0;
cls.protocol = CP_QUAKE3; cls.protocol = CP_QUAKE3;
break; break;
#endif #endif
#ifdef Q2CLIENT #ifdef Q2CLIENT
case GT_QUAKE2: case GT_QUAKE2:
pext1 = 0;
pext2 = 0;
cls.protocol = CP_QUAKE2; cls.protocol = CP_QUAKE2;
break; break;
#endif #endif
default: default:
cl.movesequence = 0; cl.movesequence = 0;
if (!strcmp(cl_loopbackprotocol.string, "qw")) 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; cls.protocol = CP_QUAKEWORLD;
else if (!strcmp(cl_loopbackprotocol.string, "fitz")) //actually proquake, because we might as well use the extra angles 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; cls.protocol_nq = CPNQ_DP7;
} }
else if (progstype == PROG_QW) else if (progstype == PROG_QW)
{
cls.protocol = CP_QUAKEWORLD; cls.protocol = CP_QUAKEWORLD;
pext1 = Net_PextMask(1, false);
pext2 = Net_PextMask(2, false);
}
else else
cls.protocol = CP_NETQUAKE; 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; break;
} }
@ -701,7 +731,7 @@ void CL_CheckForResend (void)
} }
NET_AdrToString(data, sizeof(data), &adr); 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) while(NET_GetPacket (NS_SERVER, 0) >= 0)
{ {
} }
@ -733,7 +763,7 @@ void CL_CheckForResend (void)
CL_ConnectToDarkPlaces("", &adr); CL_ConnectToDarkPlaces("", &adr);
} }
else else
CL_SendConnectPacket (8192-16, Net_PextMask(1, false), Net_PextMask(2, false), false); CL_SendConnectPacket (8192-16, pext1, pext2, false);
return; return;
} }
#endif #endif
@ -2686,7 +2716,7 @@ void CLNQ_ConnectionlessPacket(void)
#endif #endif
void CL_MVDUpdateSpectator (void); void CL_MVDUpdateSpectator (void);
void CL_WriteDemoMessage (sizebuf_t *msg); void CL_WriteDemoMessage (sizebuf_t *msg, int payloadoffset);
/* /*
================= =================
CL_ReadPackets CL_ReadPackets
@ -2776,6 +2806,7 @@ void CL_ReadPackets (void)
// cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence - 3; // cls.netchan.incoming_sequence = cls.netchan.outgoing_sequence - 3;
case NQP_RELIABLE://reliable case NQP_RELIABLE://reliable
MSG_ChangePrimitives(cls.netchan.netprim); MSG_ChangePrimitives(cls.netchan.netprim);
CL_WriteDemoMessage (&net_message, msg_readcount);
CLNQ_ParseServerMessage (); CLNQ_ParseServerMessage ();
break; break;
} }
@ -2805,7 +2836,7 @@ void CL_ReadPackets (void)
else if (!Netchan_Process(&cls.netchan)) else if (!Netchan_Process(&cls.netchan))
continue; // wasn't accepted for some reason 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) if (cls.netchan.incoming_sequence > cls.netchan.outgoing_sequence)
{ //server should not be responding to packets we have not sent yet { //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_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); CL_AllowIndependantSendCmd(false);
// fetch results from server // fetch results from server

View file

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

View file

@ -21,7 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "winquake.h" #include "winquake.h"
cvar_t cl_nopred = SCVAR("cl_nopred","0"); cvar_t cl_nopred = SCVAR("cl_nopred","0");
extern cvar_t cl_lerp_players;
cvar_t cl_pushlatency = SCVAR("pushlatency","-999"); cvar_t cl_pushlatency = SCVAR("pushlatency","-999");
extern float pm_airaccelerate; extern float pm_airaccelerate;
@ -504,7 +503,7 @@ void CL_CalcCrouch (playerview_t *pv, float stepchange)
float LerpAngles360(float to, float from, float frac) float LerpAngles360(float to, float from, float frac)
{ {
int delta; float delta;
delta = (from-to); delta = (from-to);
if (delta > 180) if (delta > 180)
@ -636,6 +635,7 @@ short LerpAngles16(short to, short from, float frac)
void CL_CalcClientTime(void) void CL_CalcClientTime(void)
{ {
extern float demtime;
if (cls.protocol != CP_QUAKE3) if (cls.protocol != CP_QUAKE3)
{ {
float oldst = realtime; float oldst = realtime;
@ -670,7 +670,13 @@ void CL_CalcClientTime(void)
max = min; max = min;
if (max) 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 else
cl.servertime = 0; 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].stats[STAT_WEAPONFRAME] = state->u.q1.weaponframe;
cl.playerview[i].statsf[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 *org;
float stepheight = 0; float stepheight = 0;
float netfps = cl_netfps.value; float netfps = cl_netfps.value;
if (!netfps) if (!netfps)
{ {
//every video frame has its own input frame. //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)) if (cl.paused && !(cls.demoplayback!=DPB_MVD && cls.demoplayback!=DPB_EZTV) && (!cl.spectator || !pv->cam_auto))
return; 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) if (!cl.validsequence)
{ {
return; return;
} }
if (cl.movesequence - cl.ackedmovesequence >= UPDATE_BACKUP-1)
{ //lagging like poo. if (cl.intermission==1 && cls.protocol == CP_QUAKEWORLD)
if (!cl.intermission) //keep the angles working though. {
VectorCopy (pv->viewangles, pv->simangles); VectorCopy (pv->intermissionangles, pv->simangles);
return; 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]; from = &cl.inframes[cl.validsequence & UPDATE_MASK];
cmdfrom = &cl.outframes[cl.ackedmovesequence & UPDATE_MASK]; cmdfrom = &cl.outframes[cl.ackedmovesequence & UPDATE_MASK];
if (!cl.intermission)
{
VectorCopy (pv->viewangles, pv->simangles);
}
vel = from->playerstate[pv->playernum].velocity; vel = from->playerstate[pv->playernum].velocity;
org = from->playerstate[pv->playernum].origin; 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; lerpents_t *le = NULL;
if (pv->nolocalplayer) if (pv->nolocalplayer)
le = &cl.lerpents[pv->cam_spec_track+1]; {
if (pv->viewentity < cl.maxlerpents)
le = &cl.lerpents[pv->viewentity];
}
else 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; vel = vec3_origin;
} }
@ -1056,7 +1071,7 @@ fixedorg:
if (pv->viewentity && pv->viewentity != pv->playernum+1 && CL_MayLerp()) if (pv->viewentity && pv->viewentity != pv->playernum+1 && CL_MayLerp())
{ {
float f; 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]; lerpents_t *le = &cl.lerpplayers[pv->cam_spec_track];
org = le->origin; org = le->origin;

View file

@ -396,7 +396,7 @@ typedef struct
// demo recording info must be here, because record is started before // demo recording info must be here, because record is started before
// entering a map (and clearing client_state_t) // entering a map (and clearing client_state_t)
qboolean demorecording; int demorecording; //1=QW, 2=NQ
vfsfile_t *demooutfile; vfsfile_t *demooutfile;
enum{DPB_NONE,DPB_QUAKEWORLD,DPB_MVD,DPB_EZTV, 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 // the client maintains its own idea of view angles, which are
// sent to the server each frame. And only reset at level change // sent to the server each frame. And only reset at level change
// and teleport times // and teleport times
vec3_t viewangles; vec3_t viewangles; //current angles
vec3_t viewanglechange; vec3_t viewanglechange; //angles set by input code this frame
vec3_t intermissionangles; //absolute angles for intermission
vec3_t gravitydir; vec3_t gravitydir;
// pitch drifting vars // pitch drifting vars
@ -545,10 +546,6 @@ struct playerview_s
int waterlevel; //for smartjump int waterlevel; //for smartjump
float punchangle; // temporary view kick from weapon firing 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_time; //various view knockbacks.
float v_dmg_roll; float v_dmg_roll;
@ -601,10 +598,11 @@ typedef struct
int oldparsecount; int oldparsecount;
int oldvalidsequence; 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 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 int validsequence; // this is the sequence number of the last good
// packetentity_t we got. If this is 0, we can't // packetentity_t we got. If this is 0, we can't
// render a frame yet // render a frame yet
int movesequence; // int movesequence; // client->server frames
int spectator; int spectator;
@ -723,8 +721,12 @@ typedef struct
float predicted_step_time; float predicted_step_time;
float predicted_step; float predicted_step;
//interpolation+snapshots
float packfrac;
packet_entities_t *currentpackentities; packet_entities_t *currentpackentities;
packet_entities_t *previouspackentities;
float currentpacktime; float currentpacktime;
qboolean do_lerp_players;
int teamplay; int teamplay;
@ -1393,6 +1395,7 @@ void Stats_NewMap(void);
enum uploadfmt; enum uploadfmt;
typedef struct typedef struct
{ {
char *drivername;
void *(VARGS *createdecoder)(char *name); void *(VARGS *createdecoder)(char *name);
void *(VARGS *decodeframe)(void *ctx, qboolean nosound, enum uploadfmt *fmt, int *width, int *height); void *(VARGS *decodeframe)(void *ctx, qboolean nosound, enum uploadfmt *fmt, int *width, int *height);
void (VARGS *doneframe)(void *ctx, void *img); void (VARGS *doneframe)(void *ctx, void *img);
@ -1407,6 +1410,7 @@ typedef struct
void (VARGS *changestream) (void *ctx, char *streamname); void (VARGS *changestream) (void *ctx, char *streamname);
} media_decoder_funcs_t; } media_decoder_funcs_t;
typedef struct { 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_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_video) (void *ctx, void *data, int frame, int width, int height);
void (VARGS *capture_audio) (void *ctx, void *data, int bytes); 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; range = 0;
if (range > 1) if (range > 1)
range = 1; range = 1;
option->slider.vx = x;
x -= 8; x -= 8;
Font_BeginString(font_conchar, x, y, &x, &y); Font_BeginString(font_conchar, x, y, &x, &y);
x = Font_DrawChar(x, y, 0xe080 | CON_WHITEMASK); 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 range = option->current;
float delta; float delta;
float ix = option->vx;
float ex = ix + 10*8;
if (option->smallchange) if (option->smallchange)
delta = option->smallchange; delta = option->smallchange;
else else
@ -1263,8 +1267,6 @@ void MC_Slider_Key(menuslider_t *option, int key)
if (range < option->min) if (range < option->min)
range = option->min; range = option->min;
option->current = range; option->current = range;
if (option->var)
Cvar_SetValue(option->var, range);
} }
else if (key == K_RIGHTARROW || key == K_MWHEELUP) 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) if (range > option->max)
range = option->max; range = option->max;
option->current = range; 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) 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) if (range > option->max)
range = option->max; range = option->max;
option->current = range; option->current = range;
if (option->var)
Cvar_SetValue(option->var, range);
} }
else else
return; return;
S_LocalSound ("misc/menu2.wav"); 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) 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: changed:
if (combo->cvar && combo->numoptions) if (combo->cvar && combo->numoptions)
Cvar_Set(combo->cvar, (char *)combo->values[combo->selectedoption]); Cvar_Set(combo->cvar, (char *)combo->values[combo->selectedoption]);
S_LocalSound ("misc/menu2.wav");
} }
else if (key == K_LEFTARROW) else if (key == K_LEFTARROW)
{ {

View file

@ -2488,18 +2488,19 @@ int captureframe;
qboolean captureframeforce; qboolean captureframeforce;
qboolean capturepaused; qboolean capturepaused;
cvar_t capturerate = SCVAR("capturerate", "30"); cvar_t capturerate = CVAR("capturerate", "30");
#if defined(WINAVI) #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 #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 #endif
cvar_t capturesound = SCVAR("capturesound", "1"); cvar_t capturesound = CVAR("capturesound", "1");
cvar_t capturesoundchannels = SCVAR("capturesoundchannels", "1"); cvar_t capturesoundchannels = CVAR("capturesoundchannels", "1");
cvar_t capturesoundbits = SCVAR("capturesoundbits", "8"); cvar_t capturesoundbits = CVAR("capturesoundbits", "8");
cvar_t capturemessage = SCVAR("capturemessage", ""); cvar_t capturemessage = CVAR("capturemessage", "");
qboolean recordingdemo; qboolean recordingdemo;
media_encoder_funcs_t *capturedriver[8];
media_encoder_funcs_t *currentcapture_funcs; media_encoder_funcs_t *currentcapture_funcs;
void *currentcapture_ctx; void *currentcapture_ctx;
@ -2509,7 +2510,9 @@ void *currentcapture_ctx;
/*screenshot capture*/ /*screenshot capture*/
struct capture_raw_ctx struct capture_raw_ctx
{ {
int frames;
char videonameprefix[MAX_QPATH]; char videonameprefix[MAX_QPATH];
char videonameextension[16];
vfsfile_t *audio; 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)); 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)); Q_strncpyz(ctx->videonameprefix, streamname, sizeof(ctx->videonameprefix));
ctx->audio = NULL; ctx->audio = NULL;
if (*sndkhz) 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; struct capture_raw_ctx *ctx = vctx;
char filename[MAX_OSPATH]; 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); SCR_ScreenShot(filename, data, width, height);
} }
static void QDECL capture_raw_audio (void *vctx, void *data, int bytes) 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) static void QDECL capture_raw_end (void *vctx)
{ {
struct capture_raw_ctx *ctx = 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); Z_Free(ctx);
} }
static media_encoder_funcs_t capture_raw = static media_encoder_funcs_t capture_raw =
{ {
"raw",
capture_raw_begin, capture_raw_begin,
capture_raw_video, capture_raw_video,
capture_raw_audio, 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); hr = qAVIMakeCompressedStream(&ctx->compressed_video_stream, ctx->uncompressed_video_stream, &opts, NULL);
if (FAILED(hr)) if (FAILED(hr))
{ {
Con_Printf("Failed to init compressor\n"); Con_Printf("AVIMakeCompressedStream failed. check codec.\n");
capture_avi_end(ctx); capture_avi_end(ctx);
return NULL; 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)); hr = qAVIStreamSetFormat(avi_video_stream(ctx), 0, &bitmap_info_header, sizeof(BITMAPINFOHEADER));
if (FAILED(hr)) if (FAILED(hr))
{ {
Con_Printf("Failed to set format\n"); Con_Printf("AVIStreamSetFormat failed\n");
capture_avi_end(ctx); capture_avi_end(ctx);
return NULL; 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.dwRate = stream_header.dwScale * (unsigned long)ctx->wave_format.nSamplesPerSec;
stream_header.dwSampleSize = ctx->wave_format.nBlockAlign; 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); hr = qAVIFileCreateStreamA(ctx->file, &ctx->uncompressed_audio_stream, &stream_header);
if (FAILED(hr)) 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; data[i+2] = temp;
} }
//write it //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))) 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) 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 = static media_encoder_funcs_t capture_avi =
{ {
"avi",
capture_avi_begin, capture_avi_begin,
capture_avi_video, capture_avi_video,
capture_avi_audio, capture_avi_audio,
capture_avi_end capture_avi_end
}; };
#else
media_encoder_funcs_t capture_avi =
{
NULL,
NULL,
NULL,
NULL
};
#endif #endif
@ -3106,28 +3113,23 @@ void Media_RecordFilm_f (void)
capturelastvideotime = realtime = 0; capturelastvideotime = realtime = 0;
captureframe = 0; captureframe = 0;
if (*fourcc) for (i = 0; i < sizeof(pluginencodersfunc)/sizeof(pluginencodersfunc[0]); i++)
{
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++)
{ {
if (pluginencodersfunc[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) if (capturesound.ival)
@ -3900,6 +3902,7 @@ void Media_Init(void)
Cvar_Register(&capturemessage, "AVI capture controls"); Cvar_Register(&capturemessage, "AVI capture controls");
Cvar_Register(&capturesound, "AVI capture controls"); Cvar_Register(&capturesound, "AVI capture controls");
Cvar_Register(&capturerate, "AVI capture controls"); Cvar_Register(&capturerate, "AVI capture controls");
Cvar_Register(&capturedriver, "AVI capture controls");
Cvar_Register(&capturecodec, "AVI capture controls"); Cvar_Register(&capturecodec, "AVI capture controls");
#if defined(WINAVI) #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); 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) void M_Menu_Audio_f (void)
{ {
menu_t *menu; int y;
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; 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; // extern cvar_t snd_noextraupdate, snd_eax, precache;
#ifdef VOICECHAT #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 #endif
extern char **soundoutdevicecodes, **soundoutdevicenames;
static const char *soundqualityoptions[] = { static const char *soundqualityoptions[] = {
"11025 Hz", "11025 Hz",
@ -275,11 +277,43 @@ void M_Menu_Audio_f (void)
NULL 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[] = { menubulk_t bulk[] = {
MB_REDTEXT("Sound Options", false), MB_REDTEXT("Sound Options", false),
MB_TEXT("\x80\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x82", false), MB_TEXT("\x80\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x81\x82", false),
MB_SPACING(8), 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_SLIDER("Volume", volume, 0, 1, 0.1, NULL),
MB_COMBOCVAR("Speaker Setup", snd_speakers, speakeroptions, speakervalues, NULL), MB_COMBOCVAR("Speaker Setup", snd_speakers, speakeroptions, speakervalues, NULL),
MB_COMBOCVAR("Frequency", snd_khz, soundqualityoptions, soundqualityvalues, 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_SLIDER("Mixahead", _snd_mixahead, 0, 1, 0.05, NULL),
MB_CHECKBOXCVAR("Disable All Sounds", nosound, 0), MB_CHECKBOXCVAR("Disable All Sounds", nosound, 0),
MB_SPACING(4), 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("Player Sound Volume", snd_playersoundvolume, 0, 1, 0.1, NULL),
MB_SLIDER("Ambient Volume", ambient_level, 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), MB_SLIDER("Ambient Fade", ambient_fade, 0, 1000, 1, NULL),
@ -300,17 +331,28 @@ void M_Menu_Audio_f (void)
// removed music buffer // removed music buffer
// removed precache // removed precache
// removed eax2 // removed eax2
MB_CHECKBOXCVAR("Multiple Devices", snd_usemultipledevices, 0),
// remove no extra update // remove no extra update
MB_CHECKBOXCVAR("Sound While Inactive", snd_inactive, 0), MB_CHECKBOXCVAR("Sound While Inactive", snd_inactive, 0),
MB_SPACING(4), 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("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() MB_END()
}; };
menu = M_Options_Title(&y, 0);
MC_AddBulk(menu, bulk, 16, 216, y); MC_AddBulk(menu, bulk, 16, 216, y);
} }

View file

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

View file

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

View file

@ -2721,7 +2721,7 @@ ping time frags name
Font_BeginString(font_conchar, x+24, y, &cx, &cy); \ Font_BeginString(font_conchar, x+24, y, &cx, &cy); \
Font_DrawChar(cx, cy, num[2] | 0xe000 | CON_WHITEMASK); \ 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)) \ (!cl.spectator && k == pv->playernum)) \
{ \ { \
Font_BeginString(font_conchar, x, y, &cx, &cy); \ Font_BeginString(font_conchar, x, y, &cx, &cy); \
@ -2774,6 +2774,9 @@ void Sbar_DeathmatchOverlay (int start)
int startx, rank_width; int startx, rank_width;
playerview_t *pv = r_refdef.playerview; playerview_t *pv = r_refdef.playerview;
if (!pv)
return;
if (largegame) if (largegame)
skip = 8; 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. Much of it is stripped, to try and get it clean/compliant.
Missing features: 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: listener velocity calculations (currently ugly).
FIXME: does not track entity velocities, so no dopler (awkward, quake move playing sounds at all). FIXME: does not track entity velocities, so no dopler (awkward, quake doesn't move playing sounds at all).
FIXME: no eax (underwater). FIXME: no eax / efx (underwater reverb etc).
FIXME: a capture device would be useful (voice chat). FIXME: a capture device would be useful (voice chat).
*/ */
@ -34,6 +30,8 @@ typedef char ALboolean;
typedef int ALsizei; typedef int ALsizei;
typedef void ALvoid; typedef void ALvoid;
static dllhandle_t *openallib;
static qboolean openallib_tried;
static AL_API ALenum (AL_APIENTRY *palGetError)( void ); 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 *palSourcef)( ALuint sid, ALenum param, ALfloat value );
static AL_API void (AL_APIENTRY *palSourcei)( ALuint sid, ALenum param, ALint 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 *palSpeedOfSound)( ALfloat value );
static AL_API void (AL_APIENTRY *palDistanceModel)( ALenum distanceModel ); 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_NONE 0
#define AL_FALSE 0 #define AL_FALSE 0
@ -72,9 +74,14 @@ static AL_API void (AL_APIENTRY *palDistanceModel)( ALenum distanceModel );
#define AL_BUFFER 0x1009 #define AL_BUFFER 0x1009
#define AL_GAIN 0x100A #define AL_GAIN 0x100A
#define AL_ORIENTATION 0x100F #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_REFERENCE_DISTANCE 0x1020
#define AL_ROLLOFF_FACTOR 0x1021 #define AL_ROLLOFF_FACTOR 0x1021
#define AL_MAX_DISTANCE 0x1023 #define AL_MAX_DISTANCE 0x1023
#define AL_SOURCE_TYPE 0x1027
#define AL_STREAMING 0x1029
#define AL_FORMAT_MONO8 0x1100 #define AL_FORMAT_MONO8 0x1100
#define AL_FORMAT_MONO16 0x1101 #define AL_FORMAT_MONO16 0x1101
#define AL_FORMAT_STEREO8 0x1102 #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_DEFAULT_DEVICE_SPECIFIER 0x1004
#define ALC_DEVICE_SPECIFIER 0x1005 #define ALC_DEVICE_SPECIFIER 0x1005
#define ALC_EXTENSIONS 0x1006 #define ALC_EXTENSIONS 0x1006
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
//#include "AL/alut.h" //#include "AL/alut.h"
//#include "AL/al.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" #define SOUNDVARS "OpenAL variables"
@ -155,30 +223,35 @@ static void S_Info(void);
static void S_Shutdown_f(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_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_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_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_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_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_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 static cvar_t s_al_static_listener = CVAR("s_al_static_listener", "0"); //cheat
#define NUM_SOURCES MAX_CHANNELS typedef struct
static ALuint source[NUM_SOURCES]; {
#define NUM_SOURCES MAX_CHANNELS
ALuint source[NUM_SOURCES];
static ALCdevice *OpenAL_Device; ALCdevice *OpenAL_Device;
static ALCcontext *OpenAL_Context; 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. // Velocity of the listener.
static ALfloat ListenVel[] = { 0.0, 0.0, 0.0 }; ALfloat ListenVel[3];// = { 0.0, 0.0, 0.0 };
// Orientation of the listener. (first 3 elements are "at", second 3 are "up") // 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 }; 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) static void PrintALError(char *string)
{ {
ALenum err; ALenum err;
@ -212,7 +285,7 @@ static void PrintALError(char *string)
Con_Printf("OpenAL - %s: %x: %s\n",string,err,text); 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 fmt;
unsigned int size; unsigned int size;
@ -246,7 +319,7 @@ void OpenAL_LoadCache(sfx_t *s, sfxcache_t *sc)
return; return;
} }
PrintALError("pre Buffer Data"); PrintALError("pre Buffer Data");
palGenBuffers(1, &s->openal_buffer); palGenBuffers(1, bufptr);
/*openal is inconsistant and supports only 8bit unsigned or 16bit signed*/ /*openal is inconsistant and supports only 8bit unsigned or 16bit signed*/
if (sc->width == 1) if (sc->width == 1)
{ {
@ -257,11 +330,11 @@ void OpenAL_LoadCache(sfx_t *s, sfxcache_t *sc)
{ {
tmp[i] = src[i]+128; tmp[i] = src[i]+128;
} }
palBufferData(s->openal_buffer, fmt, tmp, size, sc->speed); palBufferData(*bufptr, fmt, tmp, size, sc->speed);
free(tmp); free(tmp);
} }
else 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 //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) void OpenAL_CvarInit(void)
{ {
Cvar_Register(&s_al_enable, SOUNDVARS);
Cvar_Register(&s_al_debug, SOUNDVARS); Cvar_Register(&s_al_debug, SOUNDVARS);
Cvar_Register(&s_al_max_distance, SOUNDVARS); Cvar_Register(&s_al_max_distance, SOUNDVARS);
Cvar_Register(&s_al_dopplerfactor, SOUNDVARS); Cvar_Register(&s_al_dopplerfactor, SOUNDVARS);
@ -283,111 +355,58 @@ void OpenAL_CvarInit(void)
} }
extern float voicevolumemod; 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); oalinfo_t *oali = sc->handle;
VectorCopy(origin, ListenPos);
ListenOri[0] = forward[0]; VectorScale(velocity, s_al_velocityscale.value, oali->ListenVel);
ListenOri[1] = forward[1]; VectorCopy(origin, oali->ListenPos);
ListenOri[2] = forward[2];
ListenOri[3] = up[0]; oali->ListenOri[0] = forward[0];
ListenOri[4] = up[1]; oali->ListenOri[1] = forward[1];
ListenOri[5] = up[2]; 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) if (!s_al_static_listener.value)
{ {
palListenerf(AL_GAIN, volume.value*voicevolumemod); palListenerf(AL_GAIN, volume.value*voicevolumemod);
palListenerfv(AL_POSITION, ListenPos); palListenerfv(AL_POSITION, oali->ListenPos);
palListenerfv(AL_VELOCITY, ListenVel); palListenerfv(AL_VELOCITY, oali->ListenVel);
palListenerfv(AL_ORIENTATION, ListenOri); 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) static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned int schanged)
{ {
oalinfo_t *oali = sc->handle;
ALuint src; ALuint src;
sfx_t *sfx = chan->sfx; sfx_t *sfx = chan->sfx;
float pitch; 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) if (!src)
{ {
//not currently playing. be prepared to create one
if (!sfx || chan->master_vol == 0) if (!sfx || chan->master_vol == 0)
return; return;
palGenSources(1, &src); palGenSources(1, &src);
source[chan - sc->channel] = src; //unable to start a new sound source, give up.
schanged = true; 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"); PrintALError("pre start sound");
@ -395,33 +414,75 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned
if (schanged && src) if (schanged && src)
palSourceStop(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?*/ /*just wanted to stop it?*/
if (!sfx || chan->master_vol == 0) if (!sfx || chan->master_vol == 0)
{ {
if (src) if (src)
{ {
palDeleteBuffers(1, &src); palDeleteSources(1, &src);
source[chan - sc->channel] = 0; oali->source[chnum] = 0;
} }
return; return;
} }
if (schanged) if (schanged || sfx->decoder.decodedata)
{ {
if (!sfx->openal_buffer) if (!sfx->openal_buffer)
{ {
sfxcache_t *sc = S_LoadSound(sfx); if (!S_LoadSound(sfx))
if (!sc) /*ack! can't start it if its not loaded!*/ return; //can't load it
return; if (sfx->decoder.decodedata)
OpenAL_LoadCache(sfx, sc); {
} 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_GAIN, chan->master_vol/255.0f);
// palSourcef(src, AL_MAX_DISTANCE, s_al_max_distance.value); if (chan->entnum == -1 || chan->entnum == cl.playerview[0].viewentity)
// palSourcef(src, AL_ROLLOFF_FACTOR, s_al_rolloff_factor.value); palSourcefv(src, AL_POSITION, vec3_origin);
palSourcefv(src, AL_POSITION, chan->origin); else
palSourcefv(src, AL_POSITION, chan->origin);
palSourcefv(src, AL_VELOCITY, vec3_origin); palSourcefv(src, AL_VELOCITY, vec3_origin);
if (schanged) if (schanged)
@ -429,17 +490,34 @@ static void OpenAL_ChannelUpdate(soundcardinfo_t *sc, channel_t *chan, unsigned
pitch = (float)chan->rate/(1<<PITCHSHIFT); pitch = (float)chan->rate/(1<<PITCHSHIFT);
palSourcef(src, AL_PITCH, pitch); 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); 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); palSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE);
palSourcef(src, AL_ROLLOFF_FACTOR, 0.0f); // palSourcef(src, AL_ROLLOFF_FACTOR, 0.0f);
} }
else else
{ {
palSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE); 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*/ /*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*)&palGetError, "alGetError"},
{(void*)&palSourcef, "alSourcef"}, {(void*)&palSourcef, "alSourcef"},
@ -493,6 +571,11 @@ static qboolean OpenAL_Init(void)
{(void*)&palSpeedOfSound, "alSpeedOfSound"}, {(void*)&palSpeedOfSound, "alSpeedOfSound"},
{(void*)&palDistanceModel, "alDistanceModel"}, {(void*)&palDistanceModel, "alDistanceModel"},
{(void*)&palGetProcAddress, "alGetProcAddress"},
{(void*)&palGetSourcei, "alGetSourcei"},
{(void*)&palSourceQueueBuffers, "alSourceQueueBuffers"},
{(void*)&palSourceUnqueueBuffers, "alSourceUnqueueBuffers"},
{(void*)&palcOpenDevice, "alcOpenDevice"}, {(void*)&palcOpenDevice, "alcOpenDevice"},
{(void*)&palcCloseDevice, "alcCloseDevice"}, {(void*)&palcCloseDevice, "alcCloseDevice"},
{(void*)&palcCreateContext, "alcCreateContext"}, {(void*)&palcCreateContext, "alcCreateContext"},
@ -503,33 +586,56 @@ static qboolean OpenAL_Init(void)
{(void*)&palcIsExtensionPresent, "alcIsExtensionPresent"}, {(void*)&palcIsExtensionPresent, "alcIsExtensionPresent"},
{NULL} {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"); Con_Printf("OpenAL is not installed\n");
return false; return false;
} }
OpenAL_Device = palcOpenDevice(NULL); if (oali->OpenAL_Context)
if (OpenAL_Device == NULL) {
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"); PrintALError("Could not init a sound device\n");
return false; return false;
} }
OpenAL_Context = palcCreateContext(OpenAL_Device, NULL); oali->OpenAL_Context = palcCreateContext(oali->OpenAL_Device, NULL);
palcMakeContextCurrent(OpenAL_Context); if (!oali->OpenAL_Context)
// palcProcessContext(OpenAL_Context); return false;
palcMakeContextCurrent(oali->OpenAL_Context);
// palcProcessContext(oali->OpenAL_Context);
//S_Info(); //S_Info();
//fixme...
palGenSources(NUM_SOURCES, source); memset(oali->source, 0, sizeof(oali->source));
PrintALError("alGensources for normal sources"); PrintALError("alGensources for normal sources");
palListenerfv(AL_POSITION, ListenPos); palListenerfv(AL_POSITION, oali->ListenPos);
palListenerfv(AL_VELOCITY, ListenVel); palListenerfv(AL_VELOCITY, oali->ListenVel);
palListenerfv(AL_ORIENTATION, ListenOri); palListenerfv(AL_ORIENTATION, oali->ListenOri);
return true; return true;
} }
@ -595,6 +701,17 @@ static void OpenAL_UnlockBuffer (soundcardinfo_t *sc, void *buffer)
static void OpenAL_SetUnderWater (soundcardinfo_t *sc, qboolean underwater) 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); //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) static void OpenAL_Shutdown (soundcardinfo_t *sc)
{ {
oalinfo_t *oali = sc->handle;
int i; int i;
palDeleteSources(NUM_SOURCES, source); palDeleteSources(NUM_SOURCES, oali->source);
/*make sure the buffers are cleared from the sound effects*/ /*make sure the buffers are cleared from the sound effects*/
for (i=0;i<num_sfx;i++) for (i=0;i<num_sfx;i++)
@ -627,28 +745,121 @@ static void OpenAL_Shutdown (soundcardinfo_t *sc)
} }
} }
palcDestroyContext(OpenAL_Context); palDeleteAuxiliaryEffectSlots(1, &oali->effectslot);
OpenAL_Context = NULL; palDeleteEffects(1, &oali->effecttype[1]);
palcCloseDevice(OpenAL_Device);
OpenAL_Device = NULL; palcDestroyContext(oali->OpenAL_Context);
palcCloseDevice(oali->OpenAL_Device);
Z_Free(oali);
} }
typedef struct {
static int OpenAL_InitCard(soundcardinfo_t *sc, int cardnum) 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) ALuint effect;
return 2; 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) palEffectf(effect, AL_EAXREVERB_DENSITY, reverb->flDensity);
return 2; 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"); Con_Printf(CON_ERROR "OpenAL init failed\n");
return false; 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->Lock = OpenAL_LockBuffer;
sc->Unlock = OpenAL_UnlockBuffer; sc->Unlock = OpenAL_UnlockBuffer;
@ -657,10 +868,10 @@ static int OpenAL_InitCard(soundcardinfo_t *sc, int cardnum)
sc->Shutdown = OpenAL_Shutdown; sc->Shutdown = OpenAL_Shutdown;
sc->GetDMAPos = OpenAL_GetDMAPos; sc->GetDMAPos = OpenAL_GetDMAPos;
sc->ChannelUpdate = OpenAL_ChannelUpdate; 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->inactive_sound = true;
sc->selfpainting = 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_speedofsound);
Cvar_ForceCallback(&s_al_dopplerfactor); Cvar_ForceCallback(&s_al_dopplerfactor);
Cvar_ForceCallback(&s_al_max_distance); 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; 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 #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); FORCE_DEFINE_GUID(IID_IKsPropertySet, 0x31efac30, 0x515c, 0x11d0, 0xa9, 0xaa, 0x00, 0xaa, 0x00, 0x61, 0xbe, 0x93);
#endif #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 #ifdef AVAIL_DSOUND
#define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c) #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); 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) static void *DSOUND_Lock(soundcardinfo_t *sc, unsigned int *sampidx)
{ {
void *ret; void *ret;
@ -96,11 +92,11 @@ static void *DSOUND_Lock(soundcardinfo_t *sc, unsigned int *sampidx)
HRESULT hresult; HRESULT hresult;
dshandle_t *dh = sc->handle; dshandle_t *dh = sc->handle;
dwSize=0; dsound_locksize=0;
reps = 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) (void**)&pbuf2, &dwSize2, 0)) != DS_OK)
{ {
if (hresult != DSERR_BUFFERLOST) 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) static void DSOUND_Unlock(soundcardinfo_t *sc, void *buffer)
{ {
dshandle_t *dh = sc->handle; 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); 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. Direct Sound.
These following defs should be moved to winquake.h somewhere. 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 SNDDMA_InitDirect
@ -537,7 +539,7 @@ SNDDMA_InitDirect
Direct-Sound support 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; extern cvar_t snd_inactive;
#if _MSC_VER > 1200 //fixme err #if _MSC_VER > 1200 //fixme err
@ -555,9 +557,24 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
qboolean primary_format_set; qboolean primary_format_set;
dshandle_t *dh; dshandle_t *dh;
char *buffer; char *buffer;
GUID guid, *dsguid;
memset (&format, 0, sizeof(format)); 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 if (sc->sn.numchannels >= 8) // 7.1 surround
{ {
format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; 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.nAvgBytesPerSec = format.Format.nSamplesPerSec
*format.Format.nBlockAlign; *format.Format.nBlockAlign;
if (!hInstDS) if (!DSOUND_InitOutputLibrary())
{ return false;
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;
sc->handle = Z_Malloc(sizeof(dshandle_t)); sc->handle = Z_Malloc(sizeof(dshandle_t));
dh = sc->handle; 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 ))) if (FAILED(CoCreateInstance( &CLSID_EAXDirectSound, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound, (void **)&dh->pDS )))
dh->pDS=NULL; dh->pDS=NULL;
else else
IDirectSound_Initialize(dh->pDS, dsndguid); {
IDirectSound_Initialize(dh->pDS, dsguid);
}
} }
if (!dh->pDS) if (!dh->pDS)
#endif #endif
#endif #endif
{ {
while ((hresult = iDirectSoundCreate(dsndguid, &dh->pDS, NULL)) != DS_OK) while ((hresult = iDirectSoundCreate(dsguid, &dh->pDS, NULL)) != DS_OK)
{ {
if (hresult != DSERR_ALLOCATED) if (hresult != DSERR_ALLOCATED)
{ {
Con_SafePrintf (": create failed\n"); Con_SafePrintf (": create failed\n");
return SND_ERROR; return false;
} }
// if (MessageBox (NULL, // if (MessageBox (NULL,
@ -672,11 +664,21 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
Con_SafePrintf (": failure\n" Con_SafePrintf (": failure\n"
" hardware already in use\n" " hardware already in use\n"
" Close the other app then use snd_restart\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); dscaps.dwSize = sizeof(dscaps);
if (DS_OK != dh->pDS->lpVtbl->GetCaps (dh->pDS, &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"); Con_SafePrintf ("No DirectSound driver installed\n");
DSOUND_Shutdown_Internal (sc); DSOUND_Shutdown_Internal (sc);
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 SND_ERROR;
} }
@ -776,7 +768,7 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
{ {
Con_SafePrintf ("DS:CreateSoundBuffer Failed"); Con_SafePrintf ("DS:CreateSoundBuffer Failed");
DSOUND_Shutdown_Internal (sc); DSOUND_Shutdown_Internal (sc);
return SND_ERROR; return false;
} }
sc->sn.numchannels = format.Format.nChannels; 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"); Con_SafePrintf ("DS:GetCaps failed\n");
DSOUND_Shutdown_Internal (sc); DSOUND_Shutdown_Internal (sc);
return SND_ERROR; return false;
} }
// if (snd_firsttime) // if (snd_firsttime)
@ -799,14 +791,14 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
{ {
Con_SafePrintf ("Set coop level failed\n"); Con_SafePrintf ("Set coop level failed\n");
DSOUND_Shutdown_Internal (sc); DSOUND_Shutdown_Internal (sc);
return SND_ERROR; return false;
} }
if (DS_OK != dh->pDSPBuf->lpVtbl->GetCaps (dh->pDSPBuf, &dsbcaps)) if (DS_OK != dh->pDSPBuf->lpVtbl->GetCaps (dh->pDSPBuf, &dsbcaps))
{ {
Con_Printf ("DS:GetCaps failed\n"); Con_Printf ("DS:GetCaps failed\n");
DSOUND_Shutdown_Internal (sc); DSOUND_Shutdown_Internal (sc);
return SND_ERROR; return false;
} }
dh->pDSBuf = dh->pDSPBuf; 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"); Con_SafePrintf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n");
DSOUND_Shutdown_Internal (sc); DSOUND_Shutdown_Internal (sc);
return SND_ERROR; return false;
} }
if (++reps > 10000) if (++reps > 10000)
{ {
Con_SafePrintf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n"); Con_SafePrintf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n");
DSOUND_Shutdown_Internal (sc); 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); IKsPropertySet_Release(dh->EaxKsPropertiesSet);
dh->EaxKsPropertiesSet = NULL; dh->EaxKsPropertiesSet = NULL;
Con_SafePrintf ("EAX 2 not supported\n"); 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. //worked. EAX is supported.
@ -903,7 +895,7 @@ static int DSOUND_InitCard_Internal (soundcardinfo_t *sc, int cardnum)
#endif #endif
#endif #endif
return SND_LOADED; return true;
} }
@ -915,23 +907,11 @@ static int DSOUND_Thread(void *arg)
{ {
soundcardinfo_t *sc = arg; soundcardinfo_t *sc = arg;
void *cond = sc->handle; void *cond = sc->handle;
int cardnum = sc->audio_fd;
sc->handle = NULL; sc->handle = NULL;
//once creating the thread, the main thread will wait for us to signal that we have inited the dsound device. //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)) if (!DSOUND_InitCard_Internal(sc, sc->name))
{
case SND_LOADED:
break;
case SND_NOMORE:
sc->audio_fd = -1;
sc->selfpainting = false; sc->selfpainting = false;
break;
default:
case SND_ERROR:
sc->selfpainting = false;
break;
}
//wake up the main thread. //wake up the main thread.
Sys_ConditionSignal(cond); Sys_ConditionSignal(cond);
@ -952,19 +932,17 @@ static int DSOUND_Thread(void *arg)
} }
#endif #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")) if (COM_CheckParm("-wavonly"))
return SND_NOMORE; return false;
if (cardnum > 5) Q_strncpyz(sc->name, device?device:"", sizeof(sc->name));
return SND_NOMORE;
#ifdef MULTITHREAD #ifdef MULTITHREAD
if (snd_mixerthread.ival) if (snd_mixerthread.ival)
{ {
void *cond; void *cond;
sc->audio_fd = cardnum;
sc->selfpainting = true; sc->selfpainting = true;
sc->handle = cond = Sys_CreateConditional(); sc->handle = cond = Sys_CreateConditional();
Sys_LockConditional(cond); Sys_LockConditional(cond);
@ -972,7 +950,7 @@ static int DSOUND_InitCard (soundcardinfo_t *sc, int cardnum)
if (!sc->thread) if (!sc->thread)
{ {
Con_SafePrintf ("Unable to create sound mixing thread\n"); 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 //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); Sys_WaitOnThread(sc->thread);
sc->thread = NULL; sc->thread = NULL;
return (sc->audio_fd==-1)?SND_NOMORE:SND_ERROR; return false;
} }
return SND_LOADED; return true;
} }
else else
#endif #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 #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", 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."); "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", cvar_t snd_device = CVARAF( "s_device", "",
"snd_multipledevices", 0, "If enabled, all output sound devices in your computer will be initialised for playback, not just the default device."); "snd_device", CVAR_ARCHIVE);
cvar_t snd_driver = CVARAF( "s_driver", "",
"snd_driver", 0);
#ifdef VOICECHAT #ifdef VOICECHAT
static void S_Voip_Play_Callback(cvar_t *var, char *oldval); 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_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_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_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); 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 #endif
@ -471,6 +469,8 @@ static qboolean S_Opus_Init(void)
} }
#endif #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; s_voip.opus.loaded = true;
return s_voip.opus.loaded; 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: case VOIP_SPEEX_WIDE:
qspeex_decoder_destroy(s_voip.decoder[sender]); qspeex_decoder_destroy(s_voip.decoder[sender]);
break; break;
case VOIP_RAW:
break;
case VOIP_OPUS: case VOIP_OPUS:
qopus_decoder_destroy(s_voip.decoder[sender]); qopus_decoder_destroy(s_voip.decoder[sender]);
break; break;
@ -520,23 +522,34 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
{ {
default: //codec not supported. default: //codec not supported.
return; return;
case VOIP_RAW:
s_voip.decsamplerate[sender] = 11025;
break;
case VOIP_SPEEX_OLD: case VOIP_SPEEX_OLD:
case VOIP_SPEEX_NARROW: case VOIP_SPEEX_NARROW:
case VOIP_SPEEX_WIDE: case VOIP_SPEEX_WIDE:
if (!S_Speex_Init()) if (!S_Speex_Init())
return; //speex not usable. return; //speex not usable.
if (codec == VOIP_SPEEX_NARROW) if (codec == VOIP_SPEEX_NARROW)
{
s_voip.decsamplerate[sender] = 8000; s_voip.decsamplerate[sender] = 8000;
s_voip.decframesize[sender] = 160;
}
else if (codec == VOIP_SPEEX_WIDE) else if (codec == VOIP_SPEEX_WIDE)
{
s_voip.decsamplerate[sender] = 16000; s_voip.decsamplerate[sender] = 16000;
s_voip.decframesize[sender] = 320;
}
else else
{
s_voip.decsamplerate[sender] = 11025; s_voip.decsamplerate[sender] = 11025;
s_voip.decframesize[sender] = 160; s_voip.decframesize[sender] = 160;
}
if (!s_voip.decoder[sender]) if (!s_voip.decoder[sender])
{ {
qspeex_bits_init(&s_voip.speex.decbits[sender]); qspeex_bits_init(&s_voip.speex.decbits[sender]);
qspeex_bits_reset(&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]) if (!s_voip.decoder[sender])
return; 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! //the lazy way to reset the codec!
if (!s_voip.decoder[sender]) 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. //opus outputs to 8, 12, 16, 24, or 48khz. pick whichever has least excess samples and resample to fit it.
if (snd_speed <= 8000) if (snd_speed <= 8000)
s_voip.decsamplerate[sender] = 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); s_voip.decoder[sender] = qopus_decoder_create(s_voip.decsamplerate[sender], 1/*FIXME: support stereo where possible*/, NULL);
if (!s_voip.decoder[sender]) if (!s_voip.decoder[sender])
return; return;
s_voip.decframesize[sender] = (sizeof(decodebuf) / sizeof(decodebuf[0])) / 2; //this is the maximum size in a single frame.
} }
else else
qopus_decoder_ctl(s_voip.decoder[sender], OPUS_RESET_STATE); 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]; decodesamps += s_voip.decframesize[sender];
break; break;
case VOIP_OPUS: 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) if (r > 0)
decodesamps += r; decodesamps += r;
break; break;
@ -606,7 +620,7 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
while (bytes > 0) 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); S_RawAudio(sender, (qbyte*)decodebuf, s_voip.decsamplerate[sender], decodesamps, 1, 2, cl_voip_play.value);
decodesamps = 0; 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]; decodesamps += s_voip.decframesize[sender];
s_voip.decseq[sender]++; s_voip.decseq[sender]++;
seq++; 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); S_RawAudio(sender, (qbyte*)decodebuf, s_voip.decsamplerate[sender], decodesamps, 1, 2, cl_voip_play.value);
decodesamps = 0; decodesamps = 0;
} }
} }
break; 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: 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 //FIXME: we shouldn't need this crap
bytes--; bytes--;
len = *start++; len = *start++;
@ -661,6 +704,7 @@ void S_Voip_Decode(unsigned int sender, unsigned int codec, unsigned int gen, un
bytes -= len; bytes -= len;
start += len; start += len;
#endif
break; break;
} }
} }
@ -718,6 +762,28 @@ void S_Voip_Parse(void)
S_Voip_Decode(sender, codec, gen, seq, bytes, data); 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) void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
{ {
unsigned char outbuf[8192]; unsigned char outbuf[8192];
@ -726,9 +792,8 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
short *start; short *start;
unsigned int initseq;//in frames unsigned int initseq;//in frames
unsigned int inittimestamp;//in samples unsigned int inittimestamp;//in samples
unsigned int i;
unsigned int samps; unsigned int samps;
float level, f; float level;
int len; int len;
float micamp = cl_voip_micamp.value; float micamp = cl_voip_micamp.value;
qboolean voipsendenable = true; 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_init(&s_voip.speex.encbits);
qspeex_bits_reset(&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) if (!s_voip.encoder)
return; return;
qspeex_encoder_ctl(s_voip.encoder, SPEEX_GET_FRAME_SIZE, &s_voip.encframesize); 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; s_voip.encsamplerate = 11025;
qspeex_encoder_ctl(s_voip.encoder, SPEEX_SET_SAMPLING_RATE, &s_voip.encsamplerate); qspeex_encoder_ctl(s_voip.encoder, SPEEX_SET_SAMPLING_RATE, &s_voip.encsamplerate);
break; break;
case VOIP_RAW:
s_voip.encsamplerate = 11025;
s_voip.encframesize = 256;
break;
case VOIP_OPUS: case VOIP_OPUS:
if (!S_Opus_Init()) if (!S_Opus_Init())
{ {
@ -845,6 +914,7 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
//use whatever is convienient. //use whatever is convienient.
s_voip.encsamplerate = 48000; s_voip.encsamplerate = 48000;
s_voip.encframesize = s_voip.encsamplerate / 400; //2.5ms frames, at a minimum. 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); s_voip.encoder = qopus_encoder_create(s_voip.encsamplerate, 1, OPUS_APPLICATION_VOIP, NULL);
if (!s_voip.encoder) if (!s_voip.encoder)
return; return;
@ -907,6 +977,8 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
case VOIP_SPEEX_WIDE: case VOIP_SPEEX_WIDE:
qspeex_bits_reset(&s_voip.speex.encbits); qspeex_bits_reset(&s_voip.speex.encbits);
break; break;
case VOIP_RAW:
break;
case VOIP_OPUS: case VOIP_OPUS:
qopus_encoder_ctl(s_voip.encoder, OPUS_RESET_STATE); qopus_encoder_ctl(s_voip.encoder, OPUS_RESET_STATE);
break; break;
@ -960,21 +1032,17 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
s_voip.speexdsp.cursamplerate = s_voip.encsamplerate; s_voip.speexdsp.cursamplerate = s_voip.encsamplerate;
} }
} }
if (s_voip.speexdsp.preproc)
qspeex_preprocess_run(s_voip.speexdsp.preproc, start);
} }
else if (s_voip.speexdsp.preproc)
for (i = 0; i < s_voip.encframesize; i++)
{ {
f = start[i] * micamp; qspeex_preprocess_state_destroy(s_voip.speexdsp.preproc);
start[i] = f; s_voip.speexdsp.preproc = NULL;
f = fabs(start[i]);
level += f*f;
} }
switch(s_voip.enccodec) switch(s_voip.enccodec)
{ {
case VOIP_SPEEX_OLD: case VOIP_SPEEX_OLD:
level += S_Voip_Preprocess(start, s_voip.encframesize, micamp);
qspeex_bits_reset(&s_voip.speex.encbits); qspeex_bits_reset(&s_voip.speex.encbits);
qspeex_encode_int(s_voip.encoder, start, &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)); 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; outbuf[outpos] = len;
outpos += 1+len; outpos += 1+len;
s_voip.encsequence++; s_voip.encsequence++;
s_voip.enctimestamp += s_voip.encframesize;
samps+=s_voip.encframesize; samps+=s_voip.encframesize;
encpos += s_voip.encframesize*2; encpos += s_voip.encframesize*2;
break; 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; ) for (; s_voip.capturepos-encpos >= s_voip.encframesize*2 && sizeof(outbuf)-outpos > 64; )
{ {
start = (short*)(s_voip.capturebuf + encpos); 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); qspeex_encode_int(s_voip.encoder, start, &s_voip.speex.encbits);
s_voip.encsequence++; s_voip.encsequence++;
samps+=s_voip.encframesize; samps+=s_voip.encframesize;
s_voip.enctimestamp += s_voip.encframesize;
encpos += s_voip.encframesize*2; encpos += s_voip.encframesize*2;
if (rtpstream) if (rtpstream) //FIXME: why?
break; break;
} }
len = qspeex_bits_write(&s_voip.speex.encbits, outbuf+outpos, sizeof(outbuf) - outpos); len = qspeex_bits_write(&s_voip.speex.encbits, outbuf+outpos, sizeof(outbuf) - outpos);
outpos += len; outpos += len;
break; 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: 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))); 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. if (len == 1) //packet does not need to be transmitted if it returns 1, supposedly. crazyness.
len = 0; len = 0;
@ -1021,20 +1145,21 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
} }
s_voip.encsequence++; s_voip.encsequence++;
samps+=s_voip.encframesize; samps+=s_voip.encframesize;
s_voip.enctimestamp += s_voip.encframesize;
encpos += s_voip.encframesize*2; encpos += s_voip.encframesize*2;
break; break;
#endif
default: default:
outbuf[outpos] = 0; outbuf[outpos] = 0;
break; break;
} }
if (rtpstream) if (rtpstream || s_voip.enccodec == VOIP_OPUS)
break; break;
} }
if (samps) if (samps)
{ {
float nl; float nl;
s_voip.enctimestamp += samps;
nl = (3000*level) / (32767.0f*32767*samps); nl = (3000*level) / (32767.0f*32767*samps);
s_voip.voiplevel = (s_voip.voiplevel*7 + nl)/8; s_voip.voiplevel = (s_voip.voiplevel*7 + nl)/8;
if (s_voip.voiplevel < cl_voip_vad_threshhold.ival && !(cl_voip_send.ival & 6)) if (s_voip.voiplevel < cl_voip_vad_threshhold.ival && !(cl_voip_send.ival & 6))
@ -1188,134 +1313,6 @@ void S_Voip_Parse(void)
#endif #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) 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 S_Startup
@ -1379,10 +1581,7 @@ S_Startup
void S_ClearRaw(void); void S_ClearRaw(void);
void S_Startup (void) void S_Startup (void)
{ {
int cardnum, drivernum; char *s;
int warningmessage=0;
int rc;
soundcardinfo_t *sc;
if (!snd_initialized) if (!snd_initialized)
return; return;
@ -1393,51 +1592,22 @@ void S_Startup (void)
snd_blocked = 0; snd_blocked = 0;
snd_speed = 0; snd_speed = 0;
for(cardnum = 0, drivernum = 0;;) for (s = snd_device.string; ; )
{ {
sc = Z_Malloc(sizeof(soundcardinfo_t)); char *sep;
rc = SNDDMA_Init(sc, &cardnum, &drivernum); s = COM_Parse(s);
if (!*com_token)
if (!rc) //error stop
{
Con_Printf("S_Startup: SNDDMA_Init failed.\n");
Z_Free(sc);
break; break;
}
if (rc == 2) //silently stop (no more cards)
{
Z_Free(sc);
break;
}
S_DefaultSpeakerConfiguration(sc); sep = strchr(com_token, ':');
if (sep)
if (sndcardinfo) *sep++ = 0;
{ //if the sample speeds of multiple soundcards do not match, it'll fail. SNDDMA_Init(com_token, sep);
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;
} }
if (!sndcardinfo)
SNDDMA_Init(NULL, NULL);
sound_started = true;//!!sndcardinfo; sound_started = true;
S_ClearRaw(); S_ClearRaw();
@ -1506,29 +1676,6 @@ void S_Control_f (void)
S_Shutdown(); S_Shutdown();
sound_started = 0; 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")) if (!Q_strcasecmp(command, "rate") || !Q_strcasecmp(command, "speed"))
{ {
@ -1612,6 +1759,8 @@ void S_Init (void)
{ {
int p; int p;
S_EnumerateDevices();
Con_DPrintf("\nSound Initialization\n"); Con_DPrintf("\nSound Initialization\n");
Cmd_AddCommand("play", S_Play); Cmd_AddCommand("play", S_Play);
@ -1653,8 +1802,7 @@ void S_Init (void)
Cvar_Register(&snd_mixerthread, "Sound controls"); Cvar_Register(&snd_mixerthread, "Sound controls");
#endif #endif
Cvar_Register(&snd_playersoundvolume, "Sound controls"); Cvar_Register(&snd_playersoundvolume, "Sound controls");
Cvar_Register(&snd_usemultipledevices, "Sound controls"); Cvar_Register(&snd_device, "Sound controls");
Cvar_Register(&snd_driver, "Sound controls");
Cvar_Register(&snd_linearresample, "Sound controls"); Cvar_Register(&snd_linearresample, "Sound controls");
Cvar_Register(&snd_linearresample_stream, "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"); 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; snd_initialized = true;
known_sfx = Z_Malloc(MAX_SFX*sizeof(sfx_t)); known_sfx = Z_Malloc(MAX_SFX*sizeof(sfx_t));
@ -1740,6 +1882,17 @@ void S_Shutdown(void)
Z_Free(known_sfx); Z_Free(known_sfx);
known_sfx = NULL; known_sfx = NULL;
num_sfx = 0; 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; target_chan->entchannel = entchannel;
SND_Spatialize(sc, target_chan); 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 return; // not audible at all
// new channel // new channel
@ -2434,9 +2587,9 @@ static void S_UpdateCard(soundcardinfo_t *sc)
} }
#ifdef AVAIL_OPENAL #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 #endif
@ -2974,6 +3127,8 @@ void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels,
if (si->channel[i].pos < 0) if (si->channel[i].pos < 0)
si->channel[i].pos = 0; si->channel[i].pos = 0;
if (si->ChannelUpdate)
si->ChannelUpdate(si, &si->channel[i], false);
break; break;
} }
if (i == si->total_chans) //this one wasn't playing. 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->sfx = &s->sfx;
c->start = 0; c->start = 0;
SND_Spatialize(si, c); SND_Spatialize(si, c);
if (si->ChannelUpdate)
si->ChannelUpdate(si, &si->channel[i], true);
} }
} }
S_UnlockMixer(); S_UnlockMixer();

View file

@ -190,9 +190,6 @@ void SNDVC_MicInput(qbyte *buffer, int samples, int freq, int width);
#ifdef AVAIL_OPENAL #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); void OpenAL_CvarInit(void);
#endif #endif
@ -236,7 +233,6 @@ extern cvar_t snd_capture;
extern float voicevolumemod; extern float voicevolumemod;
extern qboolean snd_initialized; extern qboolean snd_initialized;
extern cvar_t snd_usemultipledevices;
extern cvar_t snd_mixerthread; extern cvar_t snd_mixerthread;
extern int snd_blocked; extern int snd_blocked;
@ -254,6 +250,12 @@ void S_AmbientOn (void);
//inititalisation functions. //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); typedef int (*sounddriver) (soundcardinfo_t *sc, int cardnum);
extern sounddriver pOPENAL_InitCard; extern sounddriver pOPENAL_InitCard;
extern sounddriver pDSOUND_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 (*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 (*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 (*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 //driver-specific - if you need more stuff, you should just shove it in the handle pointer
void *thread; void *thread;
@ -303,11 +306,6 @@ struct soundcardinfo_s { //windows has one defined AFTER directsound
int snd_sent; int snd_sent;
int snd_completed; int snd_completed;
int audio_fd; int audio_fd;
// no clue how else to handle this yet!
#ifdef AVAIL_OPENAL
int openal;
#endif
}; };
extern soundcardinfo_t *sndcardinfo; extern soundcardinfo_t *sndcardinfo;

View file

@ -2421,7 +2421,10 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin
cds.cbData = strlen(qtvfile); cds.cbData = strlen(qtvfile);
cds.lpData = (void*)qtvfile; cds.lpData = (void*)qtvfile;
if (SendMessage(old, WM_COPYDATA, (WPARAM)GetDesktopWindow(), (LPARAM)&cds)) 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. return 0; //message sent.
}
} }
} }
else else

View file

@ -1250,37 +1250,8 @@ void V_CalcRefdef (playerview_t *pv)
r_refdef.vieworg[1] += 1.0/16; r_refdef.vieworg[1] += 1.0/16;
r_refdef.vieworg[2] += 1.0/16; r_refdef.vieworg[2] += 1.0/16;
if (pv->fixangle) VectorCopy (pv->simangles, r_refdef.viewangles);
{
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);
}
V_CalcViewRoll (pv); V_CalcViewRoll (pv);
V_AddIdle (pv); V_AddIdle (pv);
@ -1685,7 +1656,6 @@ void V_RenderView (void)
SCR_VRectForPlayer(&r_refdef.grect, viewnum); SCR_VRectForPlayer(&r_refdef.grect, viewnum);
V_RenderPlayerViews(r_refdef.playerview); V_RenderPlayerViews(r_refdef.playerview);
GL_Set2D (false);
Plug_SBar(r_refdef.playerview); Plug_SBar(r_refdef.playerview);
SCR_TileClear (); SCR_TileClear ();
} }

View file

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

View file

@ -2679,7 +2679,7 @@ void Cmd_set_f(void)
{ {
Cmd_ShiftArgs(1, false); Cmd_ShiftArgs(1, false);
text = Cmd_Args(); 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); text = Cmd_Argv(1);
else else
{ {

View file

@ -5737,6 +5737,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer)
byte_vec4_t *oindex; byte_vec4_t *oindex;
float *opose,*oposebase; float *opose,*oposebase;
vec2_t *otcoords; vec2_t *otcoords;
int memsize;
galiasinfo_t *gai; galiasinfo_t *gai;
@ -5846,13 +5847,16 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer)
mesh = (struct iqmmesh*)(buffer + h->ofs_meshes); 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 #ifndef SERVERONLY
sizeof(*skin)*h->num_meshes + sizeof(*shaders)*h->num_meshes + memsize += sizeof(*skin)*h->num_meshes + sizeof(*shaders)*h->num_meshes;
#endif #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); bones = (galiasbone_t*)(gai + h->num_meshes);
opos = (vecV_t*)(bones + h->num_joints); opos = (vecV_t*)(bones + h->num_joints);
onorm3 = (vec3_t*)(opos + h->num_vertexes); onorm3 = (vec3_t*)(opos + h->num_vertexes);

View file

@ -3060,6 +3060,7 @@ skipwhite:
} }
#endif #endif
//semi-colon delimited tokens
char *COM_ParseStringSet (const char *data) char *COM_ParseStringSet (const char *data)
{ {
int c; int c;
@ -3243,6 +3244,10 @@ skipwhite:
goto skipwhite; goto skipwhite;
} }
if (c == '\\' && data[1] == '\"')
{
return COM_ParseCString(data+1, token, tokenlen);
}
// handle quoted strings specially // handle quoted strings specially
if (c == '\"') if (c == '\"')
@ -3506,13 +3511,73 @@ skipwhite:
return (char*)data; 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 c;
int len; int len;
len = 0; len = 0;
com_token[0] = 0; token[0] = 0;
if (!data) if (!data)
return NULL; return NULL;
@ -3544,16 +3609,16 @@ skipwhite:
data++; data++;
while (1) while (1)
{ {
if (len >= TOKENSIZE-2) if (len >= tokenlen-2)
{ {
com_token[len] = '\0'; token[len] = '\0';
return (char*)data; return (char*)data;
} }
c = *data++; c = *data++;
if (!c) if (!c)
{ {
com_token[len] = 0; token[len] = 0;
return (char*)data; return (char*)data;
} }
if (c == '\\') if (c == '\\')
@ -3561,28 +3626,37 @@ skipwhite:
c = *data++; c = *data++;
switch(c) switch(c)
{ {
case '\r':
if (*data == '\n')
data++;
case '\n':
continue;
case 'n': case 'n':
c = '\n'; c = '\n';
break; break;
case 'r':
c = '\r';
break;
case '$':
case '\\': case '\\':
c = '\\'; case '\'':
break; break;
case '"': case '"':
c = '"'; c = '"';
com_token[len] = c; token[len] = c;
len++; len++;
continue; continue;
default: default:
com_token[len] = 0; c = '?';
return (char*)data; break;
} }
} }
if (c=='\"' || !c) if (c=='\"' || !c)
{ {
com_token[len] = 0; token[len] = 0;
return (char*)data; return (char*)data;
} }
com_token[len] = c; token[len] = c;
len++; len++;
} }
} }
@ -3590,15 +3664,15 @@ skipwhite:
// parse a regular word // parse a regular word
do do
{ {
if (len >= sizeof(com_token)-1) if (len >= tokenlen-1)
break; break;
com_token[len] = c; token[len] = c;
data++; data++;
len++; len++;
c = *data; c = *data;
} while (c>32); } while (c>32);
com_token[len] = 0; token[len] = 0;
return (char*)data; 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)) #define COM_Parse(d) COM_ParseOut(d,com_token, sizeof(com_token))
char *COM_ParseOut (const char *data, char *out, int outlen); char *COM_ParseOut (const char *data, char *out, int outlen);
char *COM_ParseStringSet (const char *data); 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_StringParse (const char *data, char *token, unsigned int tokenlen, qboolean expandmacros, qboolean qctokenize);
char *COM_ParseToken (const char *data, const char *punctuation); char *COM_ParseToken (const char *data, const char *punctuation);
char *COM_TrimString(char *str); char *COM_TrimString(char *str);
const char *COM_QuotedString(const char *string, char *buf, int buflen); //inverse of COM_StringParse
extern int com_argc; extern int com_argc;

View file

@ -1104,6 +1104,7 @@ qboolean Cvar_Command (int level)
{ {
cvar_t *v; cvar_t *v;
char *str; char *str;
char buffer[65536];
// check variables // check variables
v = Cvar_FindVar (Cmd_Argv(0)); v = Cvar_FindVar (Cmd_Argv(0));
@ -1128,29 +1129,29 @@ qboolean Cvar_Command (int level)
{ {
if (v->flags & CVAR_LATCH) if (v->flags & CVAR_LATCH)
{ {
Con_Printf ("\"%s\" is currently \"%s\"\n", v->name, v->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", v->latched_string); 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) else if (v->flags & CVAR_RENDERERLATCH)
{ {
Con_Printf ("\"%s\" is \"%s\"\n", v->name, v->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", v->latched_string); Con_Printf ("Will be changed to %s on vid_restart\n", COM_QuotedString(v->latched_string, buffer, sizeof(buffer)));
} }
else else
{ {
Con_Printf ("\"%s\" is \"%s\"\n", v->name, v->latched_string); Con_Printf ("\"%s\" is %s\n", v->name, COM_QuotedString(v->latched_string, buffer, sizeof(buffer)));
Con_Printf ("Effective value is \"%s\"\n", v->string); 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 else
{ {
if (!strcmp(v->string, v->defaultstr)) 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 else
{ {
Con_Printf ("\"%s\" is \"%s\"\n", v->name, v->string); Con_Printf ("\"%s\" is %s\n", v->name, 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)));
} }
} }
return true; return true;
@ -1170,7 +1171,7 @@ qboolean Cvar_Command (int level)
#ifndef SERVERONLY #ifndef SERVERONLY
if (Cmd_ExecLevel > RESTRICT_SERVER) if (Cmd_ExecLevel > RESTRICT_SERVER)
{ //directed at a secondary player. { //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; return true;
} }
@ -1221,6 +1222,7 @@ void Cvar_WriteVariables (vfsfile_t *f, qboolean all)
cvar_t *var; cvar_t *var;
char *val; char *val;
char *s; char *s;
char buffer[65536];
for (grp=cvar_groups ; grp ; grp=grp->next) 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_USERCREATED)
{ {
if (var->flags & CVAR_ARCHIVE) 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 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 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)); 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 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 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. bit for the reliable set.
If the sender notices that a reliable message has been dropped, it will be 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 showpackets = SCVAR("showpackets", "0");
cvar_t showdrop = SCVAR("showdrop", "0"); cvar_t showdrop = SCVAR("showdrop", "0");
cvar_t qport = SCVAR("qport", "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_replacementdeltas = CVAR("pext_replacementdeltas", "1");
cvar_t pext_nqpredinfo = CVAR("debug_pext_nqpredinfo", "0");
/*returns the entire bitmask of supported+enabled extensions*/ /*returns the entire bitmask of supported+enabled extensions*/
unsigned int Net_PextMask(int maskset, qboolean fornq) unsigned int Net_PextMask(int maskset, qboolean fornq)
@ -196,7 +197,8 @@ unsigned int Net_PextMask(int maskset, qboolean fornq)
if (pext_replacementdeltas.ival) if (pext_replacementdeltas.ival)
mask |= PEXT2_REPLACEMENTDELTAS; mask |= PEXT2_REPLACEMENTDELTAS;
//mask |= PEXT2_PREDINFO; if (fornq && pext_nqpredinfo.ival)
mask |= PEXT2_PREDINFO;
if (MAX_CLIENTS != QWMAX_CLIENTS) if (MAX_CLIENTS != QWMAX_CLIENTS)
mask |= PEXT2_MAXPLAYERS; mask |= PEXT2_MAXPLAYERS;
@ -206,6 +208,8 @@ unsigned int Net_PextMask(int maskset, qboolean fornq)
//only ones that are tested //only ones that are tested
mask &= PEXT2_VOICECHAT | PEXT2_REPLACEMENTDELTAS | PEXT2_PREDINFO; mask &= PEXT2_VOICECHAT | PEXT2_REPLACEMENTDELTAS | PEXT2_PREDINFO;
} }
else
mask &= ~PEXT2_PREDINFO;
} }
return mask; return mask;
@ -221,6 +225,7 @@ void Netchan_Init (void)
{ {
int port; int port;
Cvar_Register (&pext_nqpredinfo, "Protocol Extensions");
Cvar_Register (&pext_replacementdeltas, "Protocol Extensions"); Cvar_Register (&pext_replacementdeltas, "Protocol Extensions");
Cvar_Register (&showpackets, "Networking"); Cvar_Register (&showpackets, "Networking");
Cvar_Register (&showdrop, "Networking"); Cvar_Register (&showdrop, "Networking");

View file

@ -118,7 +118,7 @@ int PM_PointContents (vec3_t p)
model_t *pm; model_t *pm;
pm = pmove.physents[0].model; pm = pmove.physents[0].model;
if (!pm) if (!pm || pm->needload)
return FTECONTENTS_EMPTY; return FTECONTENTS_EMPTY;
pc = pm->funcs.PointContents(pm, NULL, p); pc = pm->funcs.PointContents(pm, NULL, p);
//we need this for e2m2 - waterjumping on to plats wouldn't work otherwise. //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_SETANGLEDELTA 0x00000004
#define PEXT2_REPLACEMENTDELTAS 0x00000008 #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_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. //ZQuake transparent protocol extensions.
#define Z_EXT_PM_TYPE (1<<0) // basic PM_TYPE functionality (reliable jump_held) #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_lightstyle 12 // [qbyte] [string]
#define svc_updatename 13 // [qbyte] [string] #define svc_updatename 13 // [qbyte] [string]
#define svc_updatefrags 14 // [qbyte] [short] #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_stopsound 16 // <see code>
#define svc_updatecolors 17 // [qbyte] [qbyte] [qbyte] #define svc_updatecolors 17 // [qbyte] [qbyte] [qbyte]
#define svc_particle 18 // [vec3] <variable> #define svc_particle 18 // [vec3] <variable>
@ -951,10 +951,12 @@ extern entity_state_t nullentitystate;
#define MAX_MVDPACKET_ENTITIES 196 // doesn't count nails #define MAX_MVDPACKET_ENTITIES 196 // doesn't count nails
typedef struct typedef struct
{ {
float servertime; float servertime;
int num_entities; int num_entities;
int max_entities; int max_entities;
entity_state_t *entities; entity_state_t *entities;
qboolean fixangles[MAX_SPLITS];
vec3_t fixedangles[MAX_SPLITS];
} packet_entities_t; } packet_entities_t;
typedef struct usercmd_s 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; 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 if (i == STL_MAXSTL) //silently ignore - allow other servers or clients to add stuff
continue; 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)); VectorScale((m+8), mod->clampscale, (m+8));
} }
if (e->flags & Q2RF_WEAPONMODEL && r_refdef.currentplayernum>=0) if (e->flags & Q2RF_WEAPONMODEL)
{ {
/*FIXME: no bob*/ /*FIXME: no bob*/
float iv[16]; 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) texid_t D3D9_AllocNewTexture(char *ident, int width, int height, unsigned int flags)
{ {
IDirect3DTexture9 *tx; IDirect3DTexture9 *tx;
texid_t ret = r_nulltex;
if (!FAILED(IDirect3DDevice9_CreateTexture(pD3DDev9, width, height, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tx, NULL))) /*unconditionally allocate a new texture*/
ret.ptr = tx; d3dtexture_t *tex = calloc(1, sizeof(*tex)+strlen(ident));
return ret; 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) void D3D9_DestroyTexture (texid_t tex)
{ {
IDirect3DTexture9 *tx = tex.ptr; d3dtexture_t **link;
if (tx) for (link = &d3dtextures; *link; link = &(*link)->next)
IDirect3DTexture9_Release(tx); {
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) 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); // pD3DX->lpVtbl->GetBufferSize((void*)pD3DX, &width, &height);
vid.pixelwidth = width; vid.pixelwidth = width;
vid.pixelheight = height; vid.pixelheight = height;
vid.recalc_refdef = true;
vid.width = width; vid.width = width;
vid.height = height; vid.height = height;

View file

@ -1,17 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 9.00 Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005 # 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}" Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "FTEQuake", "..\setup\setup.vdproj", "{E0EE8B50-3A75-42A9-B80A-787675979B0C}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "botlib", "botlib.vcproj", "{0018E098-B12A-4E4D-9B22-6772DA287080}" 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 EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpserver", "..\http\httpserver.vcproj", "{E6BAD203-4704-4860-9C38-D4702E9CAD7D}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "httpserver", "..\http\httpserver.vcproj", "{E6BAD203-4704-4860-9C38-D4702E9CAD7D}"
EndProject 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 Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
D3DDebug|Win32 = D3DDebug|Win32 D3DDebug|Win32 = D3DDebug|Win32
@ -66,114 +66,6 @@ Global
Release|x64 = Release|x64 Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution 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|Win32.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DDebug|x64.ActiveCfg = Release {E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DDebug|x64.ActiveCfg = Release
{E0EE8B50-3A75-42A9-B80A-787675979B0C}.D3DRelease|Win32.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.ActiveCfg = Release|Win32
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.Release|Win32.Build.0 = Release|Win32 {E6BAD203-4704-4860-9C38-D4702E9CAD7D}.Release|Win32.Build.0 = Release|Win32
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.Release|x64.ActiveCfg = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View file

@ -4062,7 +4062,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLR_DrawPortal(batch, cl.worldmodel->batches, 1); GLR_DrawPortal(batch, cl.worldmodel->batches, 1);
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, false); 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.vrect = orect;
r_refdef.pxrect = oprect; 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 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); 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.vrect = ovrect;
r_refdef.pxrect = oprect; r_refdef.pxrect = oprect;
} }
@ -4157,7 +4157,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
r_refdef.recurse = false; r_refdef.recurse = false;
GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, r_nulltex, 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.vrect = orect;
r_refdef.pxrect = oprect; 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) void GL_DestroyTexture(texid_t tex)
{ {
gltexture_t **link;
if (!tex.ref) if (!tex.ref)
return; return;
for (link = &gltextures; *link; link = &(*link)->next)
//FIXME: unlink the old one {
if (*link == (gltexture_t*)tex.ref)
qglDeleteTextures(1, &tex.num); {
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; t = *link;
if (t->com.regsequence != r_regsequence) 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); qglDeleteTextures(1, &t->texnum.num);
(*link)->next = t->next; (*link)->next = t->next;
BZ_Free(t); 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. //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) int Font_CharWidth(unsigned int charcode)
{ {
struct charcache_s *c; 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. //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) float Font_CharScaleWidth(unsigned int charcode)
{ {
struct charcache_s *c; struct charcache_s *c;

View file

@ -102,7 +102,7 @@ void R_NetGraph (void)
lost = CL_CalcNet(); lost = CL_CalcNet();
for (a=0 ; a<NET_TIMINGS ; a++) 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]); R_LineGraph (NET_TIMINGS-1-a, packet_latency[i]);
} }

View file

@ -18,7 +18,7 @@ BASE_CFLAGS=-ggdb $(USEGUI_CFLAGS)
BASE_LDFLAGS=-s BASE_LDFLAGS=-s
# set to "" for debugging # set to "" for debugging
DO_CC=$(CC) $(BASE_CFLAGS) -o $@ -c $< $(CFLAGS) DO_CC?=$(CC) $(BASE_CFLAGS) -o $@ -c $< $(CFLAGS)
lib: 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) static QCC_def_t *QCC_PR_ExpandField(QCC_def_t *ent, QCC_def_t *field)
{ {
QCC_def_t *r, *tmp; 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 || field->type->type != ev_field || !field->type->aux_type)
{ {
if (field->type->type != ev_variant) if (field->type->type != ev_variant)
{ {
QCC_PR_ParseWarning(ERR_INTERNAL, "QCC_PR_ExpandField: invalid field type"); QCC_PR_ParseErrorPrintDef(ERR_INTERNAL, field, "QCC_PR_ExpandField: invalid field type");
QCC_PR_ParsePrintDef(ERR_INTERNAL, field);
} }
r = QCC_PR_Statement(&pr_opcodes[OP_LOAD_V], ent, field, NULL); r = QCC_PR_Statement(&pr_opcodes[OP_LOAD_V], ent, field, NULL);
tmp = (void *)qccHunkAlloc (sizeof(QCC_def_t)); 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) switch(field->type->aux_type->type)
{ {
default: default:
QCC_PR_ParseWarning(ERR_INTERNAL, "QCC_PR_ExpandField: invalid field type"); QCC_PR_ParseErrorPrintDef(ERR_INTERNAL, field, "QCC_PR_ExpandField: invalid field type");
QCC_PR_ParsePrintDef(ERR_INTERNAL, field); r = field;
break; break;
case ev_integer: case ev_integer:
r = QCC_PR_Statement(&pr_opcodes[OP_LOAD_I], ent, field, NULL); 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 *singledest;
mvddest_t *SV_InitStream(int socket); 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); char *SV_MVDName2Txt(char *name);
extern cvar_t qtv_password; extern cvar_t qtv_password;
@ -1586,7 +1586,7 @@ void SV_WriteSetMVDMessage (void)
} }
void SV_MVD_SendInitialGamestate(mvddest_t *dest); void SV_MVD_SendInitialGamestate(mvddest_t *dest);
static qboolean SV_MVD_Record (mvddest_t *dest) qboolean SV_MVD_Record (mvddest_t *dest)
{ {
if (!dest) if (!dest)
return false; return false;
@ -2264,7 +2264,14 @@ void SV_MVDEasyRecord_f (void)
else else
{ {
i = Dem_CountPlayers(); 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 // Teamplay
snprintf (name, sizeof(name), "%don%d_", Dem_CountTeamPlayers(Dem_Team(1)), Dem_CountTeamPlayers(Dem_Team(2))); 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); // Con_Printf("%f\n", sv.world.physicstime);
} }
//predinfo extension reworks stats, making svc_clientdata redundant.
if (client->fteprotocolextensions2 & PEXT2_PREDINFO)
return;
bits = 0; bits = 0;
@ -1327,7 +1330,7 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
// send the data // send the data
MSG_WriteByte (msg, svc_clientdata); MSG_WriteByte (msg, svcnq_clientdata);
MSG_WriteShort (msg, bits); MSG_WriteShort (msg, bits);
if (bits & SU_EXTEND1) if (bits & SU_EXTEND1)
@ -1627,16 +1630,13 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf
else else
statsi[STAT_VIEWZOOM] = ent->xv->viewzoom*255; 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; float *statsfi;
statsf[STAT_MOVEVARS_ENTGRAVITY] = host_client->entgravity; if (client->fteprotocolextensions2 & PEXT2_PREDINFO)
statsf[STAT_MOVEVARS_MAXSPEED] = host_client->maxspeed; statsfi = statsf;
} else
if (client->protocol == SCP_DARKPLACES7) statsfi = (float*)statsi; /*dp requires a union of ints and floats, which is rather hideous...*/
{
/*note: statsf is truncated, which would mess things up*/
float *statsfi = (float*)statsi;
// statsfi[STAT_MOVEVARS_WALLFRICTION] = sv_wall // statsfi[STAT_MOVEVARS_WALLFRICTION] = sv_wall
statsfi[STAT_MOVEVARS_FRICTION] = sv_friction.value; statsfi[STAT_MOVEVARS_FRICTION] = sv_friction.value;
statsfi[STAT_MOVEVARS_WATERFRICTION] = sv_waterfriction.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_ACCELERATE] = sv_accelerate.value;
statsfi[STAT_MOVEVARS_AIRACCELERATE] = sv_airaccelerate.value; statsfi[STAT_MOVEVARS_AIRACCELERATE] = sv_airaccelerate.value;
statsfi[STAT_MOVEVARS_WATERACCELERATE] = sv_wateraccelerate.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_JUMPVELOCITY] = 270;//sv_jumpvelocity.value; //bah
statsfi[STAT_MOVEVARS_EDGEFRICTION] = sv_edgefriction.value; statsfi[STAT_MOVEVARS_EDGEFRICTION] = sv_edgefriction.value;
statsfi[STAT_MOVEVARS_MAXAIRSPEED] = host_client->maxspeed; 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 = static media_decoder_funcs_t decoderfuncs =
{ {
"avplug",
AVDec_Create, AVDec_Create,
AVDec_DisplayFrame, AVDec_DisplayFrame,
NULL,//doneframe NULL,//doneframe
@ -429,7 +430,10 @@ qintptr_t Plug_Init(qintptr_t *args)
okay |= AVDec_Init(); okay |= AVDec_Init();
okay |= AVEnc_Init(); okay |= AVEnc_Init();
if (okay) if (okay)
{
av_register_all(); av_register_all();
avcodec_register_all();
}
return okay; 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); audiocodec = avcodec_find_encoder_by_name(codecname);
if (!audiocodec) if (!audiocodec)
{ {
Con_Printf("Unsupported avplug_codec \"%s\"\n", codecname); Con_Printf("avplug: Unsupported avplug_codec \"%s\"\n", codecname);
return NULL; 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) if (videocodec)
Con_DPrintf("Using Video Codec \"%s\"\n", videocodec->name); Con_DPrintf("avplug: Using Video Codec \"%s\"\n", videocodec->name);
else else
Con_DPrintf("Not encoding video\n"); Con_DPrintf("avplug: Not encoding video\n");
if (audiocodec) if (audiocodec)
Con_DPrintf("Using Audio Codec \"%s\"\n", audiocodec->name); Con_DPrintf("avplug: Using Audio Codec \"%s\"\n", audiocodec->name);
else else
Con_DPrintf("Not encoding audio\n"); Con_DPrintf("avplug: Not encoding audio\n");
if (!videocodec && !audiocodec) if (!videocodec && !audiocodec)
{ {
Con_DPrintf("Nothing to encode!\n"); Con_DPrintf("avplug: Nothing to encode!\n");
return NULL; return NULL;
} }
@ -339,7 +339,7 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height
AVCodecContext *c = ctx->video_st->codec; AVCodecContext *c = ctx->video_st->codec;
if (avcodec_open2(c, videocodec, NULL) < 0) 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); AVEnc_End(ctx);
return NULL; return NULL;
} }
@ -360,7 +360,7 @@ static void *AVEnc_Begin (char *streamname, int videorate, int width, int height
AVCodecContext *c = ctx->audio_st->codec; AVCodecContext *c = ctx->audio_st->codec;
if (avcodec_open2(c, audiocodec, NULL) < 0) 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); AVEnc_End(ctx);
return NULL; return NULL;
} }
@ -406,6 +406,7 @@ static void AVEnc_End (void *vctx)
} }
static media_encoder_funcs_t encoderfuncs = static media_encoder_funcs_t encoderfuncs =
{ {
"avplug",
AVEnc_Begin, AVEnc_Begin,
AVEnc_Video, AVEnc_Video,
AVEnc_Audio, AVEnc_Audio,
@ -438,15 +439,15 @@ menutext 0 24 "Cancel"
qboolean AVEnc_Init(void) 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_videocodec", "mpeg4", 0, "avplug");
pCvar_Register("avplug_videocodecprofile", "", 0, "avplug"); pCvar_Register("avplug_videocodecprofile", "", 0, "avplug");
pCvar_Register("avplug_videobitrate", "4000000", 0, "avplug"); pCvar_Register("avplug_videobitrate", "4000000", 0, "avplug");
pCvar_Register("avplug_videoforcewidth", "", 0, "avplug"); pCvar_Register("avplug_videoforcewidth", "", 0, "avplug");
pCvar_Register("avplug_videoforceheight", "", 0, "avplug"); pCvar_Register("avplug_videoforceheight", "", 0, "avplug");
pCvar_Register("avplug_audiocodec", "", 0, "avplug"); pCvar_Register("avplug_audiocodec", "libmp3lame", 0, "avplug");
pCvar_Register("avplug_audiobitrate", "64000", 0, "avplug"); pCvar_Register("avplug_audiobitrate", "64000", 0, "avplug");
if (!pPlug_ExportNative("Media_VideoEncoder", &encoderfuncs)) 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>