Fix a couple of things I noticed while playing in linux.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3727 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2011-01-29 19:53:38 +00:00
parent a8c4f7f4c1
commit 4fb854e261
27 changed files with 593 additions and 177 deletions

View file

@ -852,7 +852,7 @@ ifneq ($(shell echo $(FTE_TARGET)|grep linux),)
SV_LDFLAGS=-lz SV_LDFLAGS=-lz
SV_EXE_NAME=../fteqw.sv$(BITS) SV_EXE_NAME=../fteqw.sv$(BITS)
GLCL_OBJS=$(GL_OBJS) $(GLQUAKE_OBJS) gl_vidlinuxglx.o snd_alsa.o cd_linux.o sys_linux.o GLCL_OBJS=$(GL_OBJS) $(GLQUAKE_OBJS) gl_vidlinuxglx.o snd_alsa.o snd_linux.o cd_linux.o sys_linux.o
ifeq ($(USEASM),true) ifeq ($(USEASM),true)
GLCL_OBJS+= sys_dosa.o GLCL_OBJS+= sys_dosa.o
endif endif

View file

@ -451,7 +451,7 @@ void GLDraw_Image(float x, float y, float w, float h, float s1, float t1, float
int VM_LerpTag(void *out, model_t *model, int f1, int f2, float l2, char *tagname); int VM_LerpTag(void *out, model_t *model, int f1, int f2, float l2, char *tagname);
#define VALIDATEPOINTER(o,l) if ((int)o + l >= mask || VM_POINTER(o) < offset) Host_EndGame("Call to cgame trap %i passes invalid pointer\n", fn); //out of bounds. #define VALIDATEPOINTER(o,l) if ((int)o + l >= mask || VM_POINTER(o) < offset) Host_EndGame("Call to cgame trap %u passes invalid pointer\n", (unsigned int)fn); //out of bounds.
static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, const qintptr_t *arg) static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, const qintptr_t *arg)
{ {
@ -1038,7 +1038,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
pe->DelinkTrailstate(VM_POINTER(arg[0])); pe->DelinkTrailstate(VM_POINTER(arg[0]));
break; break;
default: default:
Con_Printf("Q3CG: Bad system trap: %d\n", fn); Con_Printf("Q3CG: Bad system trap: %i\n", (int)fn);
} }
return ret; return ret;

View file

@ -2012,7 +2012,7 @@ void CL_QTVPlay_f (void)
{ {
connrequest = "QTV_EZQUAKE_EXT: 3\n"; connrequest = "QTV_EZQUAKE_EXT: 3\n";
VFS_WRITE(newf, connrequest, strlen(connrequest)); VFS_WRITE(newf, connrequest, strlen(connrequest));
connrequest = va("USERINFO: %s\n", cls.userinfo); connrequest = va("USERINFO: %s\n", cls.userinfo[0]);
VFS_WRITE(newf, connrequest, strlen(connrequest)); VFS_WRITE(newf, connrequest, strlen(connrequest));
} }
else if (raw) else if (raw)

View file

@ -688,7 +688,7 @@ void CL_FinishMove (usercmd_t *cmd, int msecs, int pnum)
void CL_DrawPrydonCursor(void) void CL_DrawPrydonCursor(void)
{ {
if (cursor_active && cl_prydoncursor.ival) if (cursor_active && cl_prydoncursor.ival > 0)
{ {
SCR_DrawCursor(cl_prydoncursor.ival); SCR_DrawCursor(cl_prydoncursor.ival);
V_StopPitchDrift (0); V_StopPitchDrift (0);
@ -1362,7 +1362,7 @@ qboolean CL_SendCmdQW (sizebuf_t *buf)
cl.frames[curframe].receivedtime = -1; // we haven't gotten a reply yet cl.frames[curframe].receivedtime = -1; // we haven't gotten a reply yet
if ((cls.fteprotocolextensions2 & PEXT2_PRYDONCURSOR) && *cl_prydoncursor.string && cls.state == ca_active) if ((cls.fteprotocolextensions2 & PEXT2_PRYDONCURSOR) && (*cl_prydoncursor.string && cl_prydoncursor.ival >= 0) && cls.state == ca_active)
{ {
vec3_t cursor_start, cursor_impact; vec3_t cursor_start, cursor_impact;
int cursor_entitynumber = 0; int cursor_entitynumber = 0;

View file

@ -541,7 +541,7 @@ void CL_SendConnectPacket (
//userinfo 0 + zquake extension info. //userinfo 0 + zquake extension info.
if (cls.protocol == CP_QUAKEWORLD) if (cls.protocol == CP_QUAKEWORLD)
Q_strncatz(data, va(" \"%s\\*z_ext\\%i\"", cls.userinfo, SUPPORTED_Z_EXTENSIONS), sizeof(data)); Q_strncatz(data, va(" \"%s\\*z_ext\\%i\"", cls.userinfo[0], SUPPORTED_Z_EXTENSIONS), sizeof(data));
else else
Q_strncatz(data, va(" \"%s\"", cls.userinfo[0]), sizeof(data)); Q_strncatz(data, va(" \"%s\"", cls.userinfo[0]), sizeof(data));
for (c = 1; c < clients; c++) for (c = 1; c < clients; c++)

View file

@ -677,7 +677,7 @@ void UI_RegisterFont(char *fontName, int pointSize, fontInfo_t *font)
#define VALIDATEPOINTER(o,l) if ((int)o + l >= mask || VM_POINTER(o) < offset) Host_EndGame("Call to ui trap %i passes invalid pointer\n", fn); //out of bounds. #define VALIDATEPOINTER(o,l) if ((int)o + l >= mask || VM_POINTER(o) < offset) Host_EndGame("Call to ui trap %i passes invalid pointer\n", (int)fn); //out of bounds.
static qintptr_t UI_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, const qintptr_t *arg) static qintptr_t UI_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, const qintptr_t *arg)
{ {
@ -1310,7 +1310,7 @@ static qintptr_t UI_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
break; break;
default: default:
Con_Printf("Q3UI: Not implemented system trap: %d\n", fn); Con_Printf("Q3UI: Not implemented system trap: %i\n", (int)fn);
return 0; return 0;
} }

View file

@ -273,7 +273,7 @@ static cblock_t Huff1Decompress (cinematics_t *cin, cblock_t in)
if (input - in.data != in.count && input - in.data != in.count+1) if (input - in.data != in.count && input - in.data != in.count+1)
{ {
Con_Printf ("Decompression overread by %i", (input - in.data) - in.count); Con_Printf ("Decompression overread by %i\n", (int)(input - in.data) - in.count);
} }
out.count = out_p - out.data; out.count = out_p - out.data;

View file

@ -876,7 +876,7 @@ void CLQ3_SendCmd(usercmd_t *cmd)
if (cls.resendinfo) if (cls.resendinfo)
{ {
cls.resendinfo = false; cls.resendinfo = false;
CLQ3_SendClientCommand("userinfo \"%s\"", cls.userinfo); CLQ3_SendClientCommand("userinfo \"%s\"", cls.userinfo[0]);
} }
ccs.serverTime = ccs.snap.serverTime + (Sys_Milliseconds()-ccs.snap.localTime); ccs.serverTime = ccs.snap.serverTime + (Sys_Milliseconds()-ccs.snap.localTime);
@ -1024,7 +1024,7 @@ void CLQ3_SendConnectPacket(netadr_t to)
msg.overflowed = msg.allowoverflow = 0; msg.overflowed = msg.allowoverflow = 0;
msg.maxsize = sizeof(data); msg.maxsize = sizeof(data);
MSG_WriteLong(&msg, -1); MSG_WriteLong(&msg, -1);
MSG_WriteString(&msg, va("connect \"\\challenge\\%i\\qport\\%i\\protocol\\%i\\ip\\%s%s\"", cls.challenge, cls.qport, PROTOCOL_VERSION_Q3, NET_AdrToString (adrbuf, sizeof(adrbuf), net_local_cl_ipadr), cls.userinfo)); MSG_WriteString(&msg, va("connect \"\\challenge\\%i\\qport\\%i\\protocol\\%i\\ip\\%s%s\"", cls.challenge, cls.qport, PROTOCOL_VERSION_Q3, NET_AdrToString (adrbuf, sizeof(adrbuf), net_local_cl_ipadr), cls.userinfo[0]));
Huff_EncryptPacket(&msg, 12); Huff_EncryptPacket(&msg, 12);
Huff_PreferedCompressionCRC(); Huff_PreferedCompressionCRC();
NET_SendPacket (NS_CLIENT, msg.cursize, msg.data, to); NET_SendPacket (NS_CLIENT, msg.cursize, msg.data, to);

View file

@ -1643,7 +1643,7 @@ void Key_Event (int pnum, int key, unsigned int unicode, qboolean down)
} }
else else
{ {
sprintf (cmd, "p%i %s\n", pnum+1, kb, key+oldstate*256); sprintf (cmd, "p%i %s\n", pnum+1, kb);
Cbuf_AddText (cmd, bindcmdlevel[key][keystate]); Cbuf_AddText (cmd, bindcmdlevel[key][keystate]);
} }
} }

View file

@ -161,7 +161,17 @@ typedef union {
#endif #endif
} texid_t; } texid_t;
typedef enum uploadfmt uploadfmt_t; typedef enum uploadfmt uploadfmt_t;
typedef enum backendmode_e backendmode_t; //not all modes accept meshes - STENCIL(intentional) and DEPTHONLY(not implemented)
typedef enum backendmode_e
{
BEM_STANDARD, //regular mode to draw surfaces akin to q3 (aka: legacy mode). lightmaps+delux+ambient
BEM_DEPTHONLY, //just a quick depth pass. textures used only for alpha test (shadowmaps).
BEM_STENCIL, //used for drawing shadow volumes to the stencil buffer.
BEM_DEPTHDARK, //a quick depth pass. textures used only for alpha test. additive textures still shown as normal.
BEM_LIGHT, //we have a valid light
BEM_SMAPLIGHTSPOT, //we have a spot light using a shadowmap
BEM_SMAPLIGHT //we have a light using a shadowmap
} backendmode_t;
typedef struct rendererinfo_s { typedef struct rendererinfo_s {
char *description; char *description;
@ -282,4 +292,4 @@ typedef struct rendererinfo_s {
#define BE_DrawMesh_List rf->BE_DrawMesh_List #define BE_DrawMesh_List rf->BE_DrawMesh_List
#define BE_DrawMesh_Single rf->BE_DrawMesh_Single #define BE_DrawMesh_Single rf->BE_DrawMesh_Single
#define BE_SubimtMeshes rf->BE_SubimtMeshes #define BE_SubimtMeshes rf->BE_SubimtMeshes
#define BE_DrawWorld rf->BE_DrawWorld #define BE_DrawWorld rf->BE_DrawWorld

View file

@ -372,7 +372,7 @@ static void PClassic_DrawParticles(void)
p->color = ramp1[(int) p->ramp]; p->color = ramp1[(int) p->ramp];
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
p->vel[i] += p->vel[i] * dvel; p->vel[i] += p->vel[i] * dvel;
p->vel[2] -= grav * 30; p->vel[2] -= grav*10;
break; break;
case pt_explode2: case pt_explode2:
p->ramp += time3; p->ramp += time3;
@ -382,7 +382,7 @@ static void PClassic_DrawParticles(void)
p->color = ramp2[(int) p->ramp]; p->color = ramp2[(int) p->ramp];
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
p->vel[i] -= p->vel[i] * frametime; p->vel[i] -= p->vel[i] * frametime;
p->vel[2] -= grav * 30; p->vel[2] -= grav*10;
break; break;
case pt_blob: case pt_blob:
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)

View file

@ -1666,6 +1666,7 @@ TRACE(("dbg: R_ApplyRenderer: clearing world\n"));
#ifdef PLUGINS #ifdef PLUGINS
Plug_ResChanged(); Plug_ResChanged();
#endif #endif
Cvar_ForceCallback(&r_particlesystem);
TRACE(("dbg: R_ApplyRenderer: starting on client state\n")); TRACE(("dbg: R_ApplyRenderer: starting on client state\n"));
if (cl.worldmodel) if (cl.worldmodel)
@ -1769,7 +1770,6 @@ TRACE(("dbg: R_ApplyRenderer: efrags\n"));
} }
else else
{ {
Cvar_ForceCallback(&r_particlesystem);
#ifdef VM_UI #ifdef VM_UI
UI_Reset(); UI_Reset();
#endif #endif

View file

@ -54,17 +54,20 @@ int (*psnd_pcm_sw_params) (snd_pcm_t *pcm, snd_pcm_sw_params_t *params);
int (*psnd_pcm_hw_params_get_buffer_size) (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val); int (*psnd_pcm_hw_params_get_buffer_size) (const snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val);
int (*psnd_pcm_hw_params_set_buffer_size_near) (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val); int (*psnd_pcm_hw_params_set_buffer_size_near) (snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val);
snd_pcm_sframes_t (*psnd_pcm_avail_update) (snd_pcm_t *pcm); snd_pcm_sframes_t (*psnd_pcm_avail_update) (snd_pcm_t *pcm);
int (*psnd_pcm_mmap_begin) (snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames);
snd_pcm_sframes_t (*psnd_pcm_mmap_commit) (snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t frames);
snd_pcm_state_t (*psnd_pcm_state) (snd_pcm_t *pcm); snd_pcm_state_t (*psnd_pcm_state) (snd_pcm_t *pcm);
int (*psnd_pcm_start) (snd_pcm_t *pcm); int (*psnd_pcm_start) (snd_pcm_t *pcm);
size_t (*psnd_pcm_hw_params_sizeof) (void); size_t (*psnd_pcm_hw_params_sizeof) (void);
size_t (*psnd_pcm_sw_params_sizeof) (void); size_t (*psnd_pcm_sw_params_sizeof) (void);
int (*psnd_pcm_mmap_begin) (snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames);
snd_pcm_sframes_t (*psnd_pcm_mmap_commit) (snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t frames);
snd_pcm_sframes_t (*psnd_pcm_writei) (snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
int (*psnd_pcm_prepare) (snd_pcm_t *pcm);
static unsigned int ALSA_GetDMAPos (soundcardinfo_t *sc) static unsigned int ALSA_MMap_GetDMAPos (soundcardinfo_t *sc)
{ {
const snd_pcm_channel_area_t *areas; const snd_pcm_channel_area_t *areas;
snd_pcm_uframes_t offset; snd_pcm_uframes_t offset;
@ -79,16 +82,10 @@ static unsigned int ALSA_GetDMAPos (soundcardinfo_t *sc)
return sc->sn.samplepos; return sc->sn.samplepos;
} }
static void ALSA_Shutdown (soundcardinfo_t *sc) static void ALSA_MMap_Submit (soundcardinfo_t *sc, int start, int end)
{ {
psnd_pcm_close (sc->handle);
}
static void ALSA_Submit (soundcardinfo_t *sc)
{
extern int soundtime;
int state; int state;
int count = sc->paintedtime - soundtime; int count = end - start;
const snd_pcm_channel_area_t *areas; const snd_pcm_channel_area_t *areas;
snd_pcm_uframes_t nframes; snd_pcm_uframes_t nframes;
snd_pcm_uframes_t offset; snd_pcm_uframes_t offset;
@ -112,6 +109,63 @@ static void ALSA_Submit (soundcardinfo_t *sc)
break; break;
} }
} }
static unsigned int ALSA_RW_GetDMAPos (soundcardinfo_t *sc)
{
int frames;
frames = psnd_pcm_avail_update(sc->handle);
if (frames >= 0)
{
sc->sn.samplepos = (sc->snd_sent + frames) * sc->sn.numchannels;
}
return sc->sn.samplepos;
}
static void ALSA_RW_Submit (soundcardinfo_t *sc, int start, int end)
{
int state;
unsigned int frames, offset, ringsize;
unsigned chunk;
int result;
int stride = sc->sn.numchannels * (sc->sn.samplebits/8);
/*we can't change the data that was already written*/
frames = end - sc->snd_sent;
if (!frames)
return;
state = psnd_pcm_state (sc->handle);
ringsize = sc->sn.samples / sc->sn.numchannels;
chunk = frames;
offset = sc->snd_sent % ringsize;
if (offset + chunk >= ringsize)
chunk = ringsize - offset;
result = psnd_pcm_writei(sc->handle, sc->sn.buffer + offset*stride, chunk);
if (result < chunk)
{
if (result >= 0)
sc->snd_sent += result;
return;
}
sc->snd_sent += chunk;
chunk = frames - chunk;
if (chunk)
{
result = psnd_pcm_writei(sc->handle, sc->sn.buffer, chunk);
if (result > 0)
sc->snd_sent += result;
}
if (state == SND_PCM_STATE_PREPARED)
psnd_pcm_start (sc->handle);
}
static void ALSA_Shutdown (soundcardinfo_t *sc)
{
psnd_pcm_close (sc->handle);
}
static void *ALSA_LockBuffer(soundcardinfo_t *sc) static void *ALSA_LockBuffer(soundcardinfo_t *sc)
{ {
@ -162,14 +216,18 @@ static qboolean Alsa_InitAlsa(void)
psnd_pcm_sw_params = dlsym(alsasharedobject, "snd_pcm_sw_params"); psnd_pcm_sw_params = dlsym(alsasharedobject, "snd_pcm_sw_params");
psnd_pcm_hw_params_get_buffer_size = dlsym(alsasharedobject, "snd_pcm_hw_params_get_buffer_size"); psnd_pcm_hw_params_get_buffer_size = dlsym(alsasharedobject, "snd_pcm_hw_params_get_buffer_size");
psnd_pcm_avail_update = dlsym(alsasharedobject, "snd_pcm_avail_update"); psnd_pcm_avail_update = dlsym(alsasharedobject, "snd_pcm_avail_update");
psnd_pcm_mmap_begin = dlsym(alsasharedobject, "snd_pcm_mmap_begin");
psnd_pcm_state = dlsym(alsasharedobject, "snd_pcm_state"); psnd_pcm_state = dlsym(alsasharedobject, "snd_pcm_state");
psnd_pcm_mmap_commit = dlsym(alsasharedobject, "snd_pcm_mmap_commit");
psnd_pcm_start = dlsym(alsasharedobject, "snd_pcm_start"); psnd_pcm_start = dlsym(alsasharedobject, "snd_pcm_start");
psnd_pcm_hw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_hw_params_sizeof"); psnd_pcm_hw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_hw_params_sizeof");
psnd_pcm_sw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_sw_params_sizeof"); psnd_pcm_sw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_sw_params_sizeof");
psnd_pcm_hw_params_set_buffer_size_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_buffer_size_near"); psnd_pcm_hw_params_set_buffer_size_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_buffer_size_near");
psnd_pcm_mmap_begin = dlsym(alsasharedobject, "snd_pcm_mmap_begin");
psnd_pcm_mmap_commit = dlsym(alsasharedobject, "snd_pcm_mmap_commit");
psnd_pcm_writei = dlsym(alsasharedobject, "snd_pcm_writei");
psnd_pcm_prepare = dlsym(alsasharedobject, "snd_pcm_prepare");
alsaworks = psnd_pcm_open alsaworks = psnd_pcm_open
&& psnd_pcm_close && psnd_pcm_close
&& psnd_strerror && psnd_strerror
@ -186,13 +244,15 @@ static qboolean Alsa_InitAlsa(void)
&& psnd_pcm_sw_params && psnd_pcm_sw_params
&& psnd_pcm_hw_params_get_buffer_size && psnd_pcm_hw_params_get_buffer_size
&& psnd_pcm_avail_update && psnd_pcm_avail_update
&& psnd_pcm_mmap_begin
&& psnd_pcm_state && psnd_pcm_state
&& psnd_pcm_mmap_commit
&& psnd_pcm_start && psnd_pcm_start
&& psnd_pcm_hw_params_sizeof && psnd_pcm_hw_params_sizeof
&& psnd_pcm_sw_params_sizeof && psnd_pcm_sw_params_sizeof
&& psnd_pcm_hw_params_set_buffer_size_near; && psnd_pcm_hw_params_set_buffer_size_near
&& psnd_pcm_mmap_begin
&& psnd_pcm_mmap_commit
&& psnd_pcm_writei && psnd_pcm_prepare
;
return alsaworks; return alsaworks;
} }
@ -212,6 +272,7 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
snd_pcm_hw_params_t *hw; snd_pcm_hw_params_t *hw;
snd_pcm_sw_params_t *sw; snd_pcm_sw_params_t *sw;
snd_pcm_uframes_t frag_size; snd_pcm_uframes_t frag_size;
qboolean mmap = false;
if (!Alsa_InitAlsa()) if (!Alsa_InitAlsa())
{ {
@ -257,11 +318,10 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
goto error; goto error;
} }
err = psnd_pcm_hw_params_set_access (pcm, hw, SND_PCM_ACCESS_MMAP_INTERLEAVED); err = psnd_pcm_hw_params_set_access (pcm, hw, mmap?SND_PCM_ACCESS_MMAP_INTERLEAVED:SND_PCM_ACCESS_RW_INTERLEAVED);
if (0 > err) if (0 > err)
{ {
Con_Printf (CON_ERROR "ALSA: Failure to set noninterleaved PCM access. %s\n" Con_Printf (CON_ERROR "ALSA: Failure to set interleaved PCM access. %s\n",
"Note: Interleaved is not supported\n",
psnd_strerror (err)); psnd_strerror (err));
goto error; goto error;
} }
@ -396,32 +456,51 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum)
goto error; goto error;
} }
sc->Lock = ALSA_LockBuffer;
sc->Unlock = ALSA_UnlockBuffer;
sc->SetWaterDistortion = ALSA_SetUnderWater;
sc->Submit = ALSA_Submit;
sc->Shutdown = ALSA_Shutdown;
sc->GetDMAPos = ALSA_GetDMAPos;
sc->sn.samples = buffer_size * sc->sn.numchannels; // mono samples in buffer sc->sn.samples = buffer_size * sc->sn.numchannels; // mono samples in buffer
sc->sn.speed = rate; sc->sn.speed = rate;
sc->handle = pcm; sc->handle = pcm;
ALSA_GetDMAPos (sc); // sets shm->buffer
sc->Lock = ALSA_LockBuffer;
//alsa doesn't seem to like high mixahead values sc->Unlock = ALSA_UnlockBuffer;
//(maybe it tells us above somehow...) sc->SetWaterDistortion = ALSA_SetUnderWater;
//so force it lower sc->Shutdown = ALSA_Shutdown;
//quake's default of 0.2 was for 10fps rendering anyway if (mmap)
//so force it down to 0.1 which is the default for halflife at least, and should give better latency
{ {
extern cvar_t _snd_mixahead; sc->GetDMAPos = ALSA_MMap_GetDMAPos;
if (_snd_mixahead.value >= 0.2) sc->Submit = ALSA_MMap_Submit;
sc->GetDMAPos(sc); // sets shm->buffer
//alsa doesn't seem to like high mixahead values
//(maybe it tells us above somehow...)
//so force it lower
//quake's default of 0.2 was for 10fps rendering anyway
//so force it down to 0.1 which is the default for halflife at least, and should give better latency
{ {
Con_Printf("Alsa Hack: _snd_mixahead forced lower\n"); extern cvar_t _snd_mixahead;
_snd_mixahead.value = 0.1; if (_snd_mixahead.value >= 0.2)
{
Con_Printf("Alsa Hack: _snd_mixahead forced lower\n");
_snd_mixahead.value = 0.1;
}
} }
} }
else
{
sc->GetDMAPos = ALSA_RW_GetDMAPos;
sc->Submit = ALSA_RW_Submit;
sc->samplequeue = sc->sn.samples;
sc->sn.buffer = malloc(sc->sn.samples * (sc->sn.samplebits/8));
err = psnd_pcm_prepare(pcm);
if (0 > err)
{
Con_Printf (CON_ERROR "ALSA: unable to prepare for use. %s\n",
psnd_strerror (err));
goto error;
}
}
return true; return true;
error: error:

View file

@ -48,9 +48,6 @@ vec3_t listener_up = {0, 0, 1};
vec3_t listener_velocity; vec3_t listener_velocity;
vec_t sound_nominal_clip_dist=1000.0; vec_t sound_nominal_clip_dist=1000.0;
int soundtime; // sample PAIRS
#define MAX_SFX 512 #define MAX_SFX 512
sfx_t *known_sfx; // hunk allocated [MAX_SFX] sfx_t *known_sfx; // hunk allocated [MAX_SFX]
int num_sfx; int num_sfx;
@ -105,6 +102,8 @@ cvar_t snd_linearresample_stream = CVARAF( "s_linearresample_stream", "0",
cvar_t snd_usemultipledevices = CVARAF( "s_multipledevices", "0", cvar_t snd_usemultipledevices = CVARAF( "s_multipledevices", "0",
"snd_multipledevices", 0); "snd_multipledevices", 0);
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);
@ -243,6 +242,7 @@ static dllfunction_t qspeexdspfuncs[] =
}; };
snd_capture_driver_t DSOUND_Capture; snd_capture_driver_t DSOUND_Capture;
snd_capture_driver_t OSS_Capture;
static qboolean S_Speex_Init(void) static qboolean S_Speex_Init(void)
{ {
@ -419,8 +419,10 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
return; return;
/*Add new drivers in order of priority*/ /*Add new drivers in order of priority*/
if (!s_speex.driver) if (!s_speex.driver || !s_speex.driver->Init)
s_speex.driver = &DSOUND_Capture; s_speex.driver = &DSOUND_Capture;
if (!s_speex.driver || !s_speex.driver->Init)
s_speex.driver = &OSS_Capture;
/*no way to capture audio, give up*/ /*no way to capture audio, give up*/
if (!s_speex.driver) if (!s_speex.driver)
@ -670,7 +672,16 @@ static int SNDDMA_Init(soundcardinfo_t *sc, int *cardnum, int *drivernum)
else else
sc->sn.samples = 0; sc->sn.samples = 0;
sd = &drivers[*drivernum]; 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) if (!sd->ptr)
return 2; //no more cards. return 2; //no more cards.
if (!*sd->ptr) //driver not loaded if (!*sd->ptr) //driver not loaded
@ -1011,6 +1022,7 @@ void S_Init (void)
Cvar_Register(&snd_playersoundvolume, "Sound controls"); Cvar_Register(&snd_playersoundvolume, "Sound controls");
Cvar_Register(&snd_usemultipledevices, "Sound controls"); Cvar_Register(&snd_usemultipledevices, "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");
@ -1847,7 +1859,7 @@ void S_UpdateCard(soundcardinfo_t *sc)
S_Update_(sc); S_Update_(sc);
} }
void GetSoundtime(soundcardinfo_t *sc) int GetSoundtime(soundcardinfo_t *sc)
{ {
int samplepos; int samplepos;
int fullsamples; int fullsamples;
@ -1858,6 +1870,12 @@ void GetSoundtime(soundcardinfo_t *sc)
// calls to S_Update. Oh well. // calls to S_Update. Oh well.
samplepos = sc->GetDMAPos(sc); samplepos = sc->GetDMAPos(sc);
samplepos -= sc->samplequeue;
if (samplepos < 0)
{
samplepos = 0;
}
if (samplepos < sc->oldsamplepos) if (samplepos < sc->oldsamplepos)
{ {
sc->buffers++; // buffer wrapped sc->buffers++; // buffer wrapped
@ -1871,7 +1889,7 @@ void GetSoundtime(soundcardinfo_t *sc)
} }
sc->oldsamplepos = samplepos; sc->oldsamplepos = samplepos;
soundtime = sc->buffers*fullsamples + samplepos/sc->sn.numchannels; return sc->buffers*fullsamples + samplepos/sc->sn.numchannels;
} }
void S_Update (void) void S_Update (void)
@ -1904,41 +1922,55 @@ void S_ExtraUpdate (void)
void S_Update_(soundcardinfo_t *sc) void S_Update_(soundcardinfo_t *sc)
{ {
int soundtime; /*in pairs*/
unsigned endtime; unsigned endtime;
int samps; int samps;
if (sc->selfpainting) if (sc->selfpainting)
return; return;
if ((snd_blocked > 0)) if (snd_blocked > 0)
{ {
if (!sc->inactive_sound) if (!sc->inactive_sound)
return; return;
} }
// Updates DMA time // Updates DMA time
GetSoundtime(sc); soundtime = GetSoundtime(sc);
// check to make sure that we haven't overshot if (sc->samplequeue)
if (sc->paintedtime < soundtime)
{ {
//Con_Printf ("S_Update_ : overflow\n"); /*device uses a write-once queue*/
sc->paintedtime = soundtime; endtime = soundtime + sc->samplequeue/sc->sn.numchannels;
soundtime = sc->paintedtime;
samps = sc->samplequeue / sc->sn.numchannels;
}
else
{
/*device uses memory-mapped output*/
// check to make sure that we haven't overshot
if (sc->paintedtime < soundtime)
{
//Con_Printf ("S_Update_ : overflow\n");
sc->paintedtime = soundtime;
}
// mix ahead of current position
endtime = soundtime + (int)(_snd_mixahead.value * sc->sn.speed);
samps = sc->sn.samples / sc->sn.numchannels;
}
if (endtime - soundtime > samps)
{
endtime = soundtime + samps;
} }
// mix ahead of current position /*DirectSound may have killed us to give priority to another app, ask to restore it*/
endtime = soundtime + (int)(_snd_mixahead.value * sc->sn.speed);
// samps = shm->samples >> (shm->numchannels-1);
samps = sc->sn.samples / sc->sn.numchannels;
if (endtime - soundtime > samps)
endtime = soundtime + samps;
if (sc->Restore) if (sc->Restore)
sc->Restore(sc); sc->Restore(sc);
S_PaintChannels (sc, endtime); S_PaintChannels (sc, endtime);
sc->Submit(sc); sc->Submit(sc, soundtime, endtime);
} }
/* /*

View file

@ -10,44 +10,106 @@
#include <stdio.h> #include <stdio.h>
#include "quakedef.h" #include "quakedef.h"
#ifdef __linux__
#include <sys/stat.h>
#endif
static int tryrates[] = { 11025, 22051, 44100, 8000, 48000 }; static int tryrates[] = { 11025, 22051, 44100, 8000, 48000 };
static void OSS_SetUnderWater(soundcardinfo_t *sc, qboolean underwater) //simply a stub. Any ideas how to actually implement this properly? static void OSS_SetUnderWater(soundcardinfo_t *sc, qboolean underwater) //simply a stub. Any ideas how to actually implement this properly?
{ {
} }
static unsigned int OSS_GetDMAPos(soundcardinfo_t *sc) static unsigned int OSS_MMap_GetDMAPos(soundcardinfo_t *sc)
{ {
struct count_info count; struct count_info count;
if (ioctl(sc->audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1) if (sc->audio_fd != -1)
{ {
perror("/dev/dsp"); if (ioctl(sc->audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1)
Con_Printf("Uh, sound dead.\n"); {
close(sc->audio_fd); perror("/dev/dsp");
return 0; Con_Printf("Uh, sound dead.\n");
close(sc->audio_fd);
sc->audio_fd = -1;
return 0;
}
// shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1);
// fprintf(stderr, "%d \r", count.ptr);
sc->sn.samplepos = count.ptr / (sc->sn.samplebits / 8);
} }
// shm->samplepos = (count.bytes / (shm->samplebits / 8)) & (shm->samples-1);
// fprintf(stderr, "%d \r", count.ptr);
sc->sn.samplepos = count.ptr / (sc->sn.samplebits / 8);
return sc->sn.samplepos; return sc->sn.samplepos;
} }
static void OSS_MMap_Submit(soundcardinfo_t *sc, int start, int end)
{
}
static unsigned int OSS_Alsa_GetDMAPos(soundcardinfo_t *sc)
{
struct audio_buf_info info;
unsigned int bytes;
if (ioctl (sc->audio_fd, SNDCTL_DSP_GETOSPACE, &info) != -1)
{
bytes = sc->snd_sent + info.bytes;
sc->sn.samplepos = bytes / (sc->sn.samplebits / 8);
}
return sc->sn.samplepos;
}
static void OSS_Alsa_Submit(soundcardinfo_t *sc, int start, int end)
{
unsigned int bytes, offset, ringsize;
unsigned chunk;
int result;
/*we can't change the data that was already written*/
bytes = end * sc->sn.numchannels * (sc->sn.samplebits/8);
bytes -= sc->snd_sent;
if (!bytes)
return;
ringsize = sc->sn.samples * (sc->sn.samplebits/8);
chunk = bytes;
offset = sc->snd_sent % ringsize;
if (offset + chunk >= ringsize)
chunk = ringsize - offset;
result = write(sc->audio_fd, sc->sn.buffer + offset, chunk);
if (result < chunk)
{
if (result >= 0)
sc->snd_sent += result;
printf("full?\n");
return;
}
sc->snd_sent += chunk;
chunk = bytes - chunk;
if (chunk)
{
result = write(sc->audio_fd, sc->sn.buffer, chunk);
if (result > 0)
sc->snd_sent += result;
}
}
static void OSS_Shutdown(soundcardinfo_t *sc) static void OSS_Shutdown(soundcardinfo_t *sc)
{ {
if (sc->sn.buffer) //close it properly, so we can go and restart it later. if (sc->sn.buffer) //close it properly, so we can go and restart it later.
munmap(sc->sn.buffer, sc->sn.samples * (sc->sn.samplebits/8)); {
if (sc->audio_fd) if (sc->Submit == OSS_Alsa_Submit)
free(sc->sn.buffer); /*if using alsa-compat, just free the buffer*/
else
munmap(sc->sn.buffer, sc->sn.samples * (sc->sn.samplebits/8));
}
if (sc->audio_fd != -1)
close(sc->audio_fd); close(sc->audio_fd);
*sc->name = '\0'; *sc->name = '\0';
} }
static void OSS_Submit(soundcardinfo_t *sc)
{
}
static void *OSS_Lock(soundcardinfo_t *sc) static void *OSS_Lock(soundcardinfo_t *sc)
{ {
return sc->sn.buffer; return sc->sn.buffer;
@ -67,6 +129,13 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
int caps; int caps;
char *snddev = NULL; char *snddev = NULL;
cvar_t *devname; cvar_t *devname;
qboolean alsadetected = false;
#ifdef __linux__
struct stat sb;
if (stat("/proc/asound", &sb) != -1)
alsadetected = true;
#endif
devname = Cvar_Get(va("snd_devicename%i", cardnum+1), cardnum?"":"/dev/dsp", 0, "Sound controls"); devname = Cvar_Get(va("snd_devicename%i", cardnum+1), cardnum?"":"/dev/dsp", 0, "Sound controls");
snddev = devname->string; snddev = devname->string;
@ -80,7 +149,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
Con_Printf("Initing OSS sound device %s\n", snddev); Con_Printf("Initing OSS sound device %s\n", snddev);
sc->audio_fd = open(snddev, O_RDWR | O_NONBLOCK); //try the primary device sc->audio_fd = open(snddev, O_WRONLY | O_NONBLOCK); //try the primary device
if (sc->audio_fd < 0) if (sc->audio_fd < 0)
{ {
perror(snddev); perror(snddev);
@ -89,7 +158,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
return 0; return 0;
} }
Q_strncpyz(sc->name, snddev, sizeof(sc->name)); Q_strncpyz(sc->name, snddev, sizeof(sc->name));
//reset it //reset it
rc = ioctl(sc->audio_fd, SNDCTL_DSP_RESET, 0); rc = ioctl(sc->audio_fd, SNDCTL_DSP_RESET, 0);
if (rc < 0) if (rc < 0)
@ -108,12 +177,6 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
OSS_Shutdown(sc); OSS_Shutdown(sc);
return 0; return 0;
} }
if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP))
{
Con_Printf(CON_ERROR "OSS: Sorry but your soundcard can't do this\n");
OSS_Shutdown(sc);
return 0;
}
//choose channels //choose channels
#ifdef SNDCTL_DSP_CHANNELS /*I'm paranoid, okay?*/ #ifdef SNDCTL_DSP_CHANNELS /*I'm paranoid, okay?*/
@ -221,33 +284,60 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
/*samples is the number of samples*channels */ /*samples is the number of samples*channels */
// memory map the dma buffer // memory map the dma buffer
sc->sn.buffer = (unsigned char *) mmap(NULL, sc->sn.samples*(sc->sn.samplebits/8), PROT_WRITE, MAP_FILE|MAP_SHARED, sc->audio_fd, 0); sc->sn.buffer = MAP_FAILED;
if (!sc->sn.buffer) if (alsadetected)
{ {
perror(snddev); Con_Printf("Alsa detected. Refusing to mmap.\n");
Con_Printf(CON_ERROR "OSS: Could not mmap %s\n", snddev);
OSS_Shutdown(sc);
return 0;
} }
else if ((caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP))
{
sc->sn.buffer = (unsigned char *) mmap(NULL, sc->sn.samples*(sc->sn.samplebits/8), PROT_WRITE, MAP_FILE|MAP_SHARED, sc->audio_fd, 0);
if (sc->sn.buffer == MAP_FAILED)
{
Con_Printf("%s: device reported mmap capability, but mmap failed.\n", snddev);
if (alsadetected)
{
char *f, *n;
f = com_argv[0];
while((n = strchr(f, '/')))
f = n + 1;
Con_Printf("Your system is running alsa.\nTry: sudo echo \"%s 0 0 direct\" > /proc/asound/card0/pcm0p/oss\n", f);
}
}
}
if (sc->sn.buffer == MAP_FAILED)
{
sc->sn.buffer = NULL;
// toggle the trigger & start her up sc->samplequeue = info.bytes / (sc->sn.samplebits/8);
tmp = 0; sc->sn.samples*=2;
rc = ioctl(sc->audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp); sc->sn.buffer = malloc(sc->sn.samples*(sc->sn.samplebits/8));
if (rc < 0) sc->Submit = OSS_Alsa_Submit;
{ sc->GetDMAPos = OSS_Alsa_GetDMAPos;
perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not toggle.\n");
OSS_Shutdown(sc);
return 0;
} }
tmp = PCM_ENABLE_OUTPUT; else
rc = ioctl(sc->audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0)
{ {
perror(snddev); // toggle the trigger & start her up
Con_Printf(CON_ERROR "OSS: Could not toggle.\n"); tmp = 0;
OSS_Shutdown(sc); rc = ioctl(sc->audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
return 0; if (rc < 0)
{
perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not toggle.\n");
OSS_Shutdown(sc);
return 0;
}
tmp = PCM_ENABLE_OUTPUT;
rc = ioctl(sc->audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
if (rc < 0)
{
perror(snddev);
Con_Printf(CON_ERROR "OSS: Could not toggle.\n");
OSS_Shutdown(sc);
return 0;
}
sc->Submit = OSS_MMap_Submit;
sc->GetDMAPos = OSS_MMap_GetDMAPos;
} }
sc->sn.samplepos = 0; sc->sn.samplepos = 0;
@ -255,12 +345,92 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum)
sc->Lock = OSS_Lock; sc->Lock = OSS_Lock;
sc->Unlock = OSS_Unlock; sc->Unlock = OSS_Unlock;
sc->SetWaterDistortion = OSS_SetUnderWater; sc->SetWaterDistortion = OSS_SetUnderWater;
sc->Submit = OSS_Submit;
sc->Shutdown = OSS_Shutdown; sc->Shutdown = OSS_Shutdown;
sc->GetDMAPos = OSS_GetDMAPos;
return 1; return 1;
} }
int (*pOSS_InitCard) (soundcardinfo_t *sc, int cardnum) = &OSS_InitCard; int (*pOSS_InitCard) (soundcardinfo_t *sc, int cardnum) = &OSS_InitCard;
#if 0//I'm unable to test due to alsa def VOICECHAT
#include <stdint.h>
void *OSS_Capture_Init(int rate)
{
int tmp;
intptr_t fd;
char *snddev = "/dev/dsp";
fd = open(snddev, O_RDONLY | O_NONBLOCK); //try the primary device
if (fd == -1)
return NULL;
#ifdef SNDCTL_DSP_CHANNELS
tmp = 1;
if (ioctl(fd, SNDCTL_DSP_CHANNELS, &tmp) != 0)
#else
tmp = 0;
if (ioctl(fd, SNDCTL_DSP_STEREO, &tmp) != 0)
#endif
{
Con_Printf("Couldn't set mono\n");
perror(snddev);
}
tmp = AFMT_S16_LE;
if (ioctl(fd, SNDCTL_DSP_SETFMT, &tmp) != 0)
{
Con_Printf("Couldn't set sample bits\n");
perror(snddev);
}
tmp = rate;
if (ioctl(fd, SNDCTL_DSP_SPEED, &tmp) != 0)
{
Con_Printf("Couldn't set capture rate\n");
perror(snddev);
}
fd++;
return (void*)fd;
}
void OSS_Capture_Start(void *ctx)
{
/*oss will automagically restart it when we next read*/
}
void OSS_Capture_Stop(void *ctx)
{
intptr_t fd = ((intptr_t)ctx)-1;
ioctl(fd, SNDCTL_DSP_RESET, NULL);
}
void OSS_Capture_Shutdown(void *ctx)
{
intptr_t fd = ((intptr_t)ctx)-1;
close(fd);
}
unsigned int OSS_Capture_Update(void *ctx, unsigned char *buffer, unsigned int minbytes, unsigned int maxbytes)
{
intptr_t fd = ((intptr_t)ctx)-1;
ssize_t res;
res = read(fd, buffer, maxbytes);
if (res < 0)
return 0;
return res;
}
snd_capture_driver_t OSS_Capture =
{
OSS_Capture_Init,
OSS_Capture_Start,
OSS_Capture_Update,
OSS_Capture_Stop,
OSS_Capture_Shutdown
};
#endif

View file

@ -277,14 +277,15 @@ struct soundcardinfo_s { //windows has one defined AFTER directsound
qboolean inactive_sound; //continue mixing for this card even when the window isn't active. qboolean inactive_sound; //continue mixing for this card even when the window isn't active.
qboolean selfpainting; //allow the sound code to call the right functions when it feels the need (not properly supported). qboolean selfpainting; //allow the sound code to call the right functions when it feels the need (not properly supported).
int paintedtime; //used in the mixer int paintedtime; //used in the mixer as last-written pos (in sample pairs)
int oldsamplepos; //this is used to track buffer wraps int oldsamplepos; //this is used to track buffer wraps
int buffers; //used to keep track of how many buffer wraps for consistant sound int buffers; //used to keep track of how many buffer wraps for consistant sound
int samplequeue; //this is the number of samples the device can enqueue. if set, DMAPos returns the write point (rather than hardware read point) (in samplepairs).
//callbacks //callbacks
void *(*Lock) (soundcardinfo_t *sc); void *(*Lock) (soundcardinfo_t *sc);
void (*Unlock) (soundcardinfo_t *sc, void *buffer); void (*Unlock) (soundcardinfo_t *sc, void *buffer);
void (*Submit) (soundcardinfo_t *sc); void (*Submit) (soundcardinfo_t *sc, int start, int end);
void (*Shutdown) (soundcardinfo_t *sc); void (*Shutdown) (soundcardinfo_t *sc);
unsigned int (*GetDMAPos) (soundcardinfo_t *sc); unsigned int (*GetDMAPos) (soundcardinfo_t *sc);
void (*SetWaterDistortion) (soundcardinfo_t *sc, qboolean underwater); void (*SetWaterDistortion) (soundcardinfo_t *sc, qboolean underwater);

View file

@ -78,6 +78,119 @@ qboolean isDedicated;
// General routines // General routines
// ======================================================================= // =======================================================================
#if 1
static int ansiremap[8] = {0, 4, 2, 6, 1, 5, 3, 7};
static void ApplyColour(unsigned int chr)
{
static int oldchar = CON_WHITEMASK;
int bg, fg;
chr &= CON_FLAGSMASK;
if (oldchar == chr)
return;
oldchar = chr;
printf("\e[0;"); // reset
if (chr & CON_BLINKTEXT)
printf("5;"); // set blink
bg = (chr & CON_BGMASK) >> CON_BGSHIFT;
fg = (chr & CON_FGMASK) >> CON_FGSHIFT;
// don't handle intensive bit for background
// as terminals differ too much in displaying \e[1;7;3?m
bg &= 0x7;
if (chr & CON_NONCLEARBG)
{
if (fg & 0x8) // intensive bit set for foreground
{
printf("1;"); // set bold/intensity ansi flag
fg &= 0x7; // strip intensive bit
}
// set foreground and background colors
printf("3%i;4%im", ansiremap[fg], ansiremap[bg]);
}
else
{
switch(fg)
{
//to get around wierd defaults (like a white background) we have these special hacks for colours 0 and 7
case COLOR_BLACK:
printf("7m"); // set inverse
break;
case COLOR_GREY:
printf("1;30m"); // treat as dark grey
break;
case COLOR_WHITE:
printf("m"); // set nothing else
break;
default:
if (fg & 0x8) // intensive bit set for foreground
{
printf("1;"); // set bold/intensity ansi flag
fg &= 0x7; // strip intensive bit
}
printf("3%im", ansiremap[fg]); // set foreground
break;
}
}
}
#include <wchar.h>
void Sys_Printf (char *fmt, ...)
{
va_list argptr;
char text[2048];
conchar_t ctext[2048];
conchar_t *c, *e;
wchar_t w;
if (nostdout)
return;
va_start (argptr,fmt);
_vsnprintf (text,sizeof(text)-1, fmt,argptr);
va_end (argptr);
if (strlen(text) > sizeof(text))
Sys_Error("memory overwrite in Sys_Printf");
e = COM_ParseFunString(CON_WHITEMASK, text, ctext, sizeof(ctext), false);
for (c = ctext; c < e; c++)
{
ApplyColour(*c);
w = *c & 0x0ffff;
if (w >= 0xe000 && w < 0xe100)
{
putc(w&0x7f, stdout);
}
else
{
/*putwc doesn't like me. force it in utf8*/
if (w >= 0x80)
{
if (w > 0x800)
{
putc(0xe0 | ((w>>12)&0x0f), stdout);
putc(0x80 | ((w>>6)&0x3f), stdout);
}
else
putc(0xc0 | ((w>>6)&0x1f), stdout);
putc(0x80 | (w&0x3f), stdout);
}
else
putc(w, stdout);
}
}
ApplyColour(CON_WHITEMASK);
}
#else
void Sys_Printf (char *fmt, ...) void Sys_Printf (char *fmt, ...)
{ {
va_list argptr; va_list argptr;
@ -100,6 +213,7 @@ void Sys_Printf (char *fmt, ...)
else else
putc(*p, stdout); putc(*p, stdout);
} }
#endif
void Sys_Quit (void) void Sys_Quit (void)
{ {
@ -405,7 +519,11 @@ dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
int i; int i;
dllhandle_t lib; dllhandle_t lib;
lib = dlopen (name, RTLD_LAZY); lib = NULL;
if (!lib)
lib = dlopen (name, RTLD_LAZY);
if (!lib)
lib = dlopen (va("%s.so", name), RTLD_LAZY);
if (!lib) if (!lib)
return NULL; return NULL;

View file

@ -80,9 +80,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//#define DYNAMIC_LIBPNG //#define DYNAMIC_LIBPNG
//#define DYNAMIC_LIBJPEG //#define DYNAMIC_LIBJPEG
#define AVAIL_FREETYPE
#ifdef _WIN32 #ifdef _WIN32
//needs testing on other platforms //needs testing on other platforms
#define AVAIL_FREETYPE
#define AVAIL_OPENAL #define AVAIL_OPENAL
#endif #endif

View file

@ -1174,6 +1174,7 @@ unsigned int Q1BSP_FatPVS (model_t *mod, vec3_t org, qbyte *pvsbuffer, unsigned
return fatbytes; return fatbytes;
} }
#endif
qboolean Q1BSP_EdictInFatPVS(model_t *mod, struct pvscache_s *ent, qbyte *pvs) qboolean Q1BSP_EdictInFatPVS(model_t *mod, struct pvscache_s *ent, qbyte *pvs)
{ {
int i; int i;
@ -1242,7 +1243,6 @@ void Q1BSP_FindTouchedLeafs(model_t *mod, struct pvscache_s *ent, float *mins, f
Q1BSP_RFindTouchedLeafs (mod, ent, mod->nodes, mins, maxs); Q1BSP_RFindTouchedLeafs (mod, ent, mod->nodes, mins, maxs);
} }
#endif
/* /*
Server only functions Server only functions
@ -1384,9 +1384,9 @@ void Q1BSP_SetModelFuncs(model_t *mod)
{ {
#ifndef CLIENTONLY #ifndef CLIENTONLY
mod->funcs.FatPVS = Q1BSP_FatPVS; mod->funcs.FatPVS = Q1BSP_FatPVS;
#endif
mod->funcs.EdictInFatPVS = Q1BSP_EdictInFatPVS; mod->funcs.EdictInFatPVS = Q1BSP_EdictInFatPVS;
mod->funcs.FindTouchedLeafs = Q1BSP_FindTouchedLeafs; mod->funcs.FindTouchedLeafs = Q1BSP_FindTouchedLeafs;
#endif
mod->funcs.LightPointValues = NULL; mod->funcs.LightPointValues = NULL;
mod->funcs.StainNode = NULL; mod->funcs.StainNode = NULL;
mod->funcs.MarkLights = NULL; mod->funcs.MarkLights = NULL;

View file

@ -901,9 +901,9 @@ static void R_SaveRTLights_f(void)
(light->flags & LFLAG_NOSHADOWS)?"!":"", light->origin[0], light->origin[1], light->origin[2], (light->flags & LFLAG_NOSHADOWS)?"!":"", light->origin[0], light->origin[1], light->origin[2],
light->radius, light->color[0], light->color[1], light->color[2], light->radius, light->color[0], light->color[1], light->color[2],
light->style-1, light->style-1,
"", 0, "", 0.0f,
0, 0, 0, 0.0f, 0.0f, 0.0f,
0, 0, 0, light->flags&(LFLAG_NORMALMODE|LFLAG_REALTIMEMODE) 0.0f, 0.0f, 0.0f, light->flags&(LFLAG_NORMALMODE|LFLAG_REALTIMEMODE)
)); ));
} }
VFS_CLOSE(f); VFS_CLOSE(f);

View file

@ -3126,7 +3126,7 @@ void Shader_DefaultCinematic(char *shortname, shader_t *s, const void *args)
"videomap %s\n" "videomap %s\n"
"}\n" "}\n"
"}\n" "}\n"
, args) , (const char*)args)
); );
} }

View file

@ -412,7 +412,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
{ {
qglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_config.ext_texture_filter_anisotropic); qglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_config.ext_texture_filter_anisotropic);
Con_SafePrintf("Anisotropic filter extension found (%dx max).\n",gl_config.ext_texture_filter_anisotropic); Con_DPrintf("Anisotropic filter extension found (%dx max).\n",gl_config.ext_texture_filter_anisotropic);
} }
if (GL_CheckExtension("GL_ARB_texture_non_power_of_two")) if (GL_CheckExtension("GL_ARB_texture_non_power_of_two"))
@ -455,7 +455,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
} }
else else
{ {
Con_SafePrintf("ARB Multitexture extensions found. Use -noamtex to disable.\n"); Con_DPrintf("ARB Multitexture extensions found. Use -noamtex to disable.\n");
} }
} }
@ -535,17 +535,6 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
qglUnmapBufferARB = (void *)getglext("glUnmapBufferARB"); qglUnmapBufferARB = (void *)getglext("glUnmapBufferARB");
} }
/*
if (GL_CheckExtension("GL_ARB_fragment_program"))
{
gl_config.arb_fragment_program = true;
qglProgramStringARB = (void *)getglext("glProgramStringARB");
qglGetProgramivARB = (void *)getglext("glGetProgramivARB");
qglBindProgramARB = (void *)getglext("glBindProgramARB");
qglGenProgramsARB = (void *)getglext("glGenProgramsARB");
}
*/
// glslang // glslang
//the gf2 to gf4 cards emulate vertex_shader and thus supports shader_objects. //the gf2 to gf4 cards emulate vertex_shader and thus supports shader_objects.
//but our code kinda requires both for clean workings. //but our code kinda requires both for clean workings.
@ -580,9 +569,12 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
qglUniform3fvARB = (void *)getglext("glUniform3fvARB"); qglUniform3fvARB = (void *)getglext("glUniform3fvARB");
qglUniform1iARB = (void *)getglext("glUniform1iARB"); qglUniform1iARB = (void *)getglext("glUniform1iARB");
qglUniform1fARB = (void *)getglext("glUniform1fARB"); qglUniform1fARB = (void *)getglext("glUniform1fARB");
Con_DPrintf("GLSL available\n");
} }
else if (gl_config.gles && gl_config.glversion >= 2) else if (gl_config.gles && gl_config.glversion >= 2)
{ {
/*core names are different from extension names (more functions too)*/
gl_config.arb_shader_objects = true; gl_config.arb_shader_objects = true;
qglCreateProgramObjectARB = (void *)getglext( "glCreateProgram"); qglCreateProgramObjectARB = (void *)getglext( "glCreateProgram");
qglDeleteProgramObject_ = (void *)getglext( "glDeleteProgram"); qglDeleteProgramObject_ = (void *)getglext( "glDeleteProgram");
@ -610,6 +602,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver)
qglUniform3fvARB = (void *)getglext("glUniform3fv"); qglUniform3fvARB = (void *)getglext("glUniform3fv");
qglUniform1iARB = (void *)getglext("glUniform1i"); qglUniform1iARB = (void *)getglext("glUniform1i");
qglUniform1fARB = (void *)getglext("glUniform1f"); qglUniform1fARB = (void *)getglext("glUniform1f");
Con_DPrintf("GLSL available\n");
} }
if (GL_CheckExtension("GL_EXT_framebuffer_object")) if (GL_CheckExtension("GL_EXT_framebuffer_object"))
@ -650,7 +643,7 @@ GLhandleARB GLSlang_CreateShader (char **precompilerconstants, char *shadersourc
GLhandleARB shader; GLhandleARB shader;
GLint compiled; GLint compiled;
char str[1024]; char str[1024];
int loglen; int loglen, i;
char *prstrings[3+16]; char *prstrings[3+16];
int strings = 0; int strings = 0;
@ -679,7 +672,6 @@ GLhandleARB GLSlang_CreateShader (char **precompilerconstants, char *shadersourc
qglGetShaderParameteriv_(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); qglGetShaderParameteriv_(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled);
if(!compiled) if(!compiled)
{ {
Con_DPrintf("Shader source:\n%s%s%s\n", prstrings[0], prstrings[1], prstrings[2], prstrings[3]);
qglGetShaderInfoLog_(shader, sizeof(str), NULL, str); qglGetShaderInfoLog_(shader, sizeof(str), NULL, str);
qglDeleteShaderObject_(shader); qglDeleteShaderObject_(shader);
switch (shadertype) switch (shadertype)
@ -705,7 +697,9 @@ GLhandleARB GLSlang_CreateShader (char **precompilerconstants, char *shadersourc
qglGetShaderInfoLog_(shader, sizeof(str), NULL, str); qglGetShaderInfoLog_(shader, sizeof(str), NULL, str);
if (strstr(str, "WARNING")) if (strstr(str, "WARNING"))
{ {
Con_Printf("Shader source:\n%s%s%s\n", prstrings[0], prstrings[1], prstrings[2], prstrings[3]); Con_Printf("Shader source:\n");
for (i = 0; i < strings; i++)
Con_Printf("%s", prstrings[i]);
Con_Printf("%s\n", str); Con_Printf("%s\n", str);
} }
} }

View file

@ -534,6 +534,26 @@ static void GetEvent(void)
ActiveApp = false; ActiveApp = false;
ClearAllStates(); ClearAllStates();
break;
case ClientMessage:
{
char *name = XGetAtomName(vid_dpy, event.xclient.message_type);
if (!strcmp(name, "WM_PROTOCOLS") && event.xclient.format == 32)
{
char *protname = XGetAtomName(vid_dpy, event.xclient.data.l[0]);
if (!strcmp(protname, "WM_DELETE_WINDOW"))
Cmd_ExecuteString("menu_quit", RESTRICT_LOCAL);
else
Con_Printf("Got message %s\n", protname);
XFree(protname);
}
else
Con_Printf("Got message %s\n", name);
XFree(name);
}
break;
default:
// Con_Printf("%x\n", event.type);
break; break;
} }
@ -739,6 +759,7 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
Window root; Window root;
XVisualInfo *visinfo; XVisualInfo *visinfo;
qboolean fullscreen = false; qboolean fullscreen = false;
Atom prots[1];
#ifdef WITH_VMODE #ifdef WITH_VMODE
int MajorVersion, MinorVersion; int MajorVersion, MinorVersion;
@ -876,9 +897,16 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
vid_window = XCreateWindow(vid_dpy, root, 0, 0, info->width, info->height, vid_window = XCreateWindow(vid_dpy, root, 0, 0, info->width, info->height,
0, visinfo->depth, InputOutput, 0, visinfo->depth, InputOutput,
visinfo->visual, mask, &attr); visinfo->visual, mask, &attr);
/*ask the window manager to stop triggering bugs in Xlib*/
prots[0] = XInternAtom(vid_dpy, "WM_DELETE_WINDOW", False);
XSetWMProtocols(vid_dpy, vid_window, prots, sizeof(prots)/sizeof(prots[0]));
/*set caption*/
XStoreName(vid_dpy, vid_window, "FTE QuakeWorld");
/*make it visibl*/
XMapWindow(vid_dpy, vid_window); XMapWindow(vid_dpy, vid_window);
/*put it somewhere*/
XMoveWindow(vid_dpy, vid_window, 0, 0); XMoveWindow(vid_dpy, vid_window, 0, 0);
#ifdef WITH_VMODE #ifdef WITH_VMODE
if (vidmode_active) { if (vidmode_active) {
XRaiseWindow(vid_dpy, vid_window); XRaiseWindow(vid_dpy, vid_window);
@ -888,7 +916,6 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
XF86VidModeSetViewPort(vid_dpy, scrnum, 0, 0); XF86VidModeSetViewPort(vid_dpy, scrnum, 0, 0);
} }
#endif #endif
XStoreName(vid_dpy, vid_window, "FTE QuakeWorld");
//hide the cursor. //hide the cursor.
XDefineCursor(vid_dpy, vid_window, CreateNullCursor(vid_dpy, vid_window)); XDefineCursor(vid_dpy, vid_window, CreateNullCursor(vid_dpy, vid_window));

View file

@ -396,18 +396,6 @@ void Shader_NeedReload(void);
mfog_t *CM_FogForOrigin(vec3_t org); mfog_t *CM_FogForOrigin(vec3_t org);
//not all modes accept meshes - STENCIL(intentional) and DEPTHONLY(not implemented)
enum backendmode_e
{
BEM_STANDARD, //regular mode to draw surfaces akin to q3 (aka: legacy mode). lightmaps+delux+ambient
BEM_DEPTHONLY, //just a quick depth pass. textures used only for alpha test (shadowmaps).
BEM_STENCIL, //used for drawing shadow volumes to the stencil buffer.
BEM_DEPTHDARK, //a quick depth pass. textures used only for alpha test. additive textures still shown as normal.
BEM_LIGHT, //we have a valid light
BEM_SMAPLIGHTSPOT, //we have a spot light using a shadowmap
BEM_SMAPLIGHT //we have a light using a shadowmap
};
#define BEF_FORCEDEPTHWRITE 1 #define BEF_FORCEDEPTHWRITE 1
#define BEF_FORCEDEPTHTEST 2 #define BEF_FORCEDEPTHTEST 2
#define BEF_FORCEADDITIVE 4 //blend dest = GL_ONE #define BEF_FORCEADDITIVE 4 //blend dest = GL_ONE

View file

@ -308,12 +308,9 @@ char *PR_VarString (progfuncs_t *progfuncs, int first)
if (G_STRING(OFS_PARM0+i*3)) if (G_STRING(OFS_PARM0+i*3))
{ {
s=G_STRING((OFS_PARM0+i*3)) + progfuncs->stringtable; s=G_STRING((OFS_PARM0+i*3)) + progfuncs->stringtable;
if (strlen(out) + strlen(s) + 1 >= sizeof(out))
return out;
strcat (out, s); strcat (out, s);
//#ifdef PARANOID
if (strlen(out)+1 >= sizeof(out))
Sys_Error("VarString (builtin call ending with strings) exceeded maximum string length of %i chars", sizeof(out));
//#endif
} }
} }
return out; return out;

View file

@ -6588,7 +6588,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s
//wait = G_FLOAT(OFS_PARM7); //wait = G_FLOAT(OFS_PARM7);
/*FIXME: not spawned - this persistant effect is created by a map object, all attributes are custom.*/ /*FIXME: not spawned - this persistant effect is created by a map object, all attributes are custom.*/
Con_Printf("FTE-H2 FIXME: ce_rain not supported!\n", efnum); Con_Printf("FTE-H2 FIXME: ce_rain not supported!\n");
return; return;
break; break;
case ce_snow: case ce_snow:
@ -6598,7 +6598,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s
//dir = G_VECTOR(OFS_PARM4); //dir = G_VECTOR(OFS_PARM4);
//count = G_FLOAT(OFS_PARM5); //count = G_FLOAT(OFS_PARM5);
/*FIXME: not spawned - this persistant effect is created by a map object (might be delay-spawned), all attributes are custom.*/ /*FIXME: not spawned - this persistant effect is created by a map object (might be delay-spawned), all attributes are custom.*/
Con_Printf("FTE-H2 FIXME: ce_snow not supported!\n", efnum); Con_Printf("FTE-H2 FIXME: ce_snow not supported!\n");
return; return;
break; break;
case ce_fountain: case ce_fountain:
@ -6608,7 +6608,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s
//colour = G_FLOAT(OFS_PARM4); //colour = G_FLOAT(OFS_PARM4);
//count = G_FLOAT(OFS_PARM5); //count = G_FLOAT(OFS_PARM5);
/*FIXME: not spawned - this persistant effect is created by a map object, all attributes are custom.*/ /*FIXME: not spawned - this persistant effect is created by a map object, all attributes are custom.*/
Con_Printf("FTE-H2 FIXME: ce_fountain not supported!\n", efnum); Con_Printf("FTE-H2 FIXME: ce_fountain not supported!\n");
return; return;
break; break;
case ce_quake: case ce_quake:
@ -6786,7 +6786,7 @@ static void QCBUILTIN PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s
return; return;
} }
Con_Printf("FTE-H2 FIXME: ce_chunk not supported!\n", efnum); Con_Printf("FTE-H2 FIXME: ce_chunk not supported!\n");
return; return;
@ -6924,7 +6924,7 @@ static void QCBUILTIN PF_h2rain_go(progfuncs_t *prinst, struct globalvars_s *pr_
float colour = G_FLOAT(OFS_PARM4); float colour = G_FLOAT(OFS_PARM4);
float count = G_FLOAT(OFS_PARM5); float count = G_FLOAT(OFS_PARM5);
*/ */
Con_DPrintf("rain go\n", (int)G_FLOAT(OFS_PARM0)); Con_DPrintf("rain go\n");
} }
static void QCBUILTIN PF_h2StopSound(progfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_h2StopSound(progfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -6949,7 +6949,7 @@ static void QCBUILTIN PF_h2whiteflash(progfuncs_t *prinst, struct globalvars_s *
broadcast a stuffcmd, I guess, to flash the screen white broadcast a stuffcmd, I guess, to flash the screen white
Only seen this occur once: after killing pravus. Only seen this occur once: after killing pravus.
*/ */
Con_DPrintf("white flash\n", (int)G_FLOAT(OFS_PARM0)); Con_DPrintf("white flash\n");
} }
static void QCBUILTIN PF_h2getstring(progfuncs_t *prinst, struct globalvars_s *pr_globals) static void QCBUILTIN PF_h2getstring(progfuncs_t *prinst, struct globalvars_s *pr_globals)

View file

@ -695,7 +695,7 @@ static void SVQ3_Adjust_Area_Portal_State(q3sharedEntity_t *ge, qboolean open)
CMQ3_SetAreaPortalState(se->areanum, se->areanum2, open); CMQ3_SetAreaPortalState(se->areanum, se->areanum2, open);
} }
#define VALIDATEPOINTER(o,l) if ((int)o + l >= mask || VM_POINTER(o) < offset) SV_Error("Call to game trap %i passes invalid pointer\n", fn); //out of bounds. #define VALIDATEPOINTER(o,l) if ((int)o + l >= mask || VM_POINTER(o) < offset) SV_Error("Call to game trap %u passes invalid pointer\n", (unsigned int)fn); //out of bounds.
static qintptr_t Q3G_SystemCalls(void *offset, unsigned int mask, qintptr_t fn, const qintptr_t *arg) static qintptr_t Q3G_SystemCalls(void *offset, unsigned int mask, qintptr_t fn, const qintptr_t *arg)
{ {
int ret = 0; int ret = 0;
@ -1392,7 +1392,7 @@ static qintptr_t Q3G_SystemCalls(void *offset, unsigned int mask, qintptr_t fn,
// notimplemented: // notimplemented:
default: default:
Con_Printf("builtin %i is not implemented\n", fn); Con_Printf("builtin %i is not implemented\n", (int)fn);
} }
return ret; return ret;
} }