tweeks and changes for android.

audio mixer revamped to cope with threads. 'cache' memory functions no longer used for audio.
added windows acm code to decode mp3 files.
audio playback rates scale with game speed. snd_playbackrate added to control the rate of new samples.
sv_gamespeed no longer needs a map change.
fixed '=' on german keymaps and in_builtinkeymap 0 (and similar issues). bug: keybind names still use US keymap.
added support for rmqe's 24bit network precision.
fixed byterate reporting to no longer be protocol-dependant (nq rates are no longer wildly inaccurate).
removed waterjumping when already dead.
fixed model matrix for viewmodels (modelview unchanged), thus fixing rtlighting on viewmodels.
Added bspx support for rgblighting, lightingdir, and (preliminary)brushlists.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4001 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2012-02-27 12:23:15 +00:00
parent db9388a297
commit 4149c85ab6
62 changed files with 2453 additions and 1210 deletions

View file

@ -57,6 +57,9 @@ DROID_NDK_PATH?=~/droid/android-ndk-r6b
DROID_SDK_PATH?=~/droid/android-sdk-linux_x86
ANT?=ant
JAVATOOL="$(JAVA_HOME)"/bin/
ifeq ($(DROID_ARCH),)
DROID_ARCH=armeabi
endif
ifeq ($(FTE_TARGET),droid)
#if we're running under windows, then we want to run some other binary
ifeq ($(shell uname -o 2>&1 | grep Cygwin),)
@ -68,22 +71,34 @@ ifeq ($(FTE_TARGET),droid)
#we're running upon windows
NDK_PATH:=$(shell cygpath -m $(DROID_NDK_PATH))
SDK_PATH:=$(shell cygpath -m $(DROID_SDK_PATH))
ifeq ($(DROID_ARCH),x86)
TOOLCHAIN:=$(NDK_PATH)/toolchains/x86-4.4.3/prebuilt/windows/bin/i686-android-linux-
else
TOOLCHAIN:=$(NDK_PATH)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-
endif
#make can't cope with absolute paths in dependancy files
NODEPS = 1
endif
DROID_API_LEVEL=4
ifeq ($(DROID_ARCH),x86)
DROID_PLAT_INC=arch-x86
#google fecked up. anything before api_level 9 will fail to compile on x86
DROID_API_LEVEL=9
else
DROID_PLAT_INC=arch-arm
#there are 3 ABI targets
#armv5 (works on all arm droids)
#armv7 (more common on 2.2+ droids)
#armv7+neon
DROID_ABI?=-mfloat-abi=softfp
endif
STRIP=$(TOOLCHAIN)strip
CC=$(TOOLCHAIN)gcc -I$(NDK_PATH)/platforms/android-$(DROID_API_LEVEL)/arch-arm/usr/include/ -DANDROID $(DROID_ABI)
DO_LD=$(CC) -Wl,-soname,libftedroid.so -shared -Wl,--no-undefined -Wl,-z,noexecstack --sysroot=$(NDK_PATH)/platforms/android-$(DROID_API_LEVEL)/arch-arm -L$(NDK_PATH)/platforms/android-$(DROID_API_LEVEL)/arch-arm/usr/lib -o $@ $(LTO_LD) $(WCFLAGS) $(CFLAGS) -llog -lc -lz -lm
CC=$(TOOLCHAIN)gcc -I$(NDK_PATH)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC)/usr/include/ -DANDROID $(DROID_ABI)
DO_LD=$(CC) -Wl,-soname,libftedroid.so -shared -Wl,--no-undefined -Wl,-z,noexecstack --sysroot=$(NDK_PATH)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC) -L$(NDK_PATH)/platforms/android-$(DROID_API_LEVEL)/$(DROID_PLAT_INC)/usr/lib -o $@ $(LTO_LD) $(WCFLAGS) $(CFLAGS) -llog -lc -lz -lm
endif
#correct the gcc build when cross compiling
@ -732,7 +747,7 @@ ifneq ($(shell echo $(FTE_TARGET)|grep linux),)
GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) gl_vidlinuxglx.o snd_alsa.o snd_linux.o cd_linux.o sys_linux.o
GL_EXE_NAME=../fteqw.gl$(BITS)
GLCL_EXE_NAME=../fteqwcl.gl$(BITS)
GL_LDFLAGS=$(GLLDFLAGS) $(GLXLDFLAGS) -lXxf86vm -lXxf86dga
GL_LDFLAGS=$(GLLDFLAGS) $(GLXLDFLAGS) -lXxf86vm -lXxf86dga -lz
GL_CFLAGS=$(GLCFLAGS) -I/usr/X11R6/include -DUSE_DGA
GLB_DIR=gl_linux$(BITS)
GLCL_DIR=glcl_linux$(BITS)
@ -740,7 +755,7 @@ ifneq ($(shell echo $(FTE_TARGET)|grep linux),)
MCL_OBJS=$(D3DGL_OBJS) $(GLQUAKE_OBJS) $(SOFTWARE_OBJS) gl_vidlinuxglx.o snd_linux.o snd_alsa.o cd_linux.o sys_linux.o
M_EXE_NAME=../fteqw$(BITS)
MCL_EXE_NAME=../fteqwcl$(BITS)
M_LDFLAGS=$(GLLDFLAGS) $(GLXLDFLAGS) -lXxf86vm -lXxf86dga
M_LDFLAGS=$(GLLDFLAGS) $(GLXLDFLAGS) -lXxf86vm -lXxf86dga -lz
M_CFLAGS=$(GLCFLAGS) -I/usr/X11R6/include
MB_DIR=m_linux$(BITS)
MCL_DIR=mcl_linux$(BITS)
@ -852,17 +867,17 @@ endif
ifeq ($(FTE_TARGET),droid)
BASELDFLAGS=
SV_DIR=sv_droid
SV_DIR=sv_droid-$(DROID_ARCH)
SV_LDFLAGS=-lz
SV_OBJS=$(COMMON_OBJS) $(SERVER_OBJS) $(PROGS_OBJS) svmodel.o sys_droid.o
SV_EXE_NAME=../libftedroid.so
SV_OBJS=$(COMMON_OBJS) $(SERVER_OBJS) $(PROGS_OBJS) svmodel.o sys_droid.o in_droid.o
SV_EXE_NAME=libftedroid.so
SV_LDFLAGS=
GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) gl_viddroid.o sys_droid.o cd_null.o snd_droid.o
GLCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(GLQUAKE_OBJS) gl_viddroid.o sys_droid.o in_droid.o cd_null.o snd_droid.o
GL_LDFLAGS=$(GLLDFLAGS)
GLB_DIR=gl_droid
GL_EXE_NAME=../libftedroid.so
GLB_DIR=gl_droid-$(DROID_ARCH)
GL_EXE_NAME=libftedroid.so
endif
SV_DIR?=sv_sdl
@ -1198,9 +1213,10 @@ droid/ftekeystore:
$(JAVATOOL)keytool -genkey -v -keystore $@ -alias autogen -keyalg RSA -keysize 2048 -validity 10000
droid-rel: droid/build.xml droid/ftekeystore
$(MAKE) FTE_TARGET=droid gl-rel
mkdir -p droid/libs/armeabi
@cp $(RELEASE_DIR)/libftedroid.so droid/libs/armeabi/
$(foreach a, $(DROID_ARCH), $(MAKE) FTE_TARGET=droid gl-rel DROID_ARCH=$a; )
@$(foreach a, $(DROID_ARCH), mkdir -p droid/libs/$a; )
-@$(foreach a, $(DROID_ARCH), cp $(RELEASE_DIR)/gl_droid-$a/libftedroid.so droid/libs/$a/libftedroid.so; )
@cd droid && $(ANT) release
ifneq ($(DROID_PACKSU),)
@echo

View file

@ -538,9 +538,9 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
break;
case CG_UPDATESCREEN: //force a buffer swap cos loading won't refresh it soon.
SCR_BeginLoadingPlaque();
if (key_dest != key_console)
scr_con_current = 0;
SCR_UpdateScreen();
SCR_EndLoadingPlaque();
break;
case CG_FS_FOPENFILE: //fopen
@ -844,7 +844,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con
break;
case CG_S_STARTSOUND:// ( vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfx )
S_StartSound(VM_LONG(arg[1]), VM_LONG(arg[2]), S_PrecacheSound(VM_FROMSTRCACHE(arg[3])), VM_POINTER(arg[0]), 1, 1, 0);
S_StartSound(VM_LONG(arg[1]), VM_LONG(arg[2]), S_PrecacheSound(VM_FROMSTRCACHE(arg[3])), VM_POINTER(arg[0]), 1, 1, 0, 0);
break;
case CG_S_ADDLOOPINGSOUND:

View file

@ -1402,6 +1402,7 @@ void CLNQ_ParseEntity(unsigned int bits)
if (!CL_CheckBaselines(num))
Host_EndGame("CLNQ_ParseEntity: check baselines failed with size %i", num);
base = cl_baselines + num;
memcpy(state, base, sizeof(*state));
state->number = num;
state->solid = ES_SOLID_BSP;
@ -1410,68 +1411,47 @@ void CLNQ_ParseEntity(unsigned int bits)
if (bits & NQU_MODEL)
state->modelindex = MSG_ReadByte ();
else
state->modelindex = base->modelindex;
if (bits & NQU_FRAME)
state->frame = MSG_ReadByte();
else
state->frame = base->frame;
if (bits & NQU_COLORMAP)
state->colormap = MSG_ReadByte();
else
state->colormap = base->colormap;
if (bits & NQU_SKIN)
state->skinnum = MSG_ReadByte();
else
state->skinnum = base->skinnum;
if (bits & NQU_EFFECTS)
state->effects = MSG_ReadByte();
else
state->effects = base->effects;
if (bits & NQU_ORIGIN1)
state->origin[0] = MSG_ReadCoord ();
else
state->origin[0] = base->origin[0];
if (bits & NQU_ANGLE1)
state->angles[0] = MSG_ReadAngle();
else
state->angles[0] = base->angles[0];
if (bits & NQU_ORIGIN2)
state->origin[1] = MSG_ReadCoord ();
else
state->origin[1] = base->origin[1];
if (bits & NQU_ANGLE2)
state->angles[1] = MSG_ReadAngle();
else
state->angles[1] = base->angles[1];
if (bits & NQU_ORIGIN3)
state->origin[2] = MSG_ReadCoord ();
else
state->origin[2] = base->origin[2];
if (bits & NQU_ANGLE3)
state->angles[2] = MSG_ReadAngle();
else
state->angles[2] = base->angles[2];
if (cls.protocol_nq == CPNQ_FITZ666)
{
if (bits & FITZU_ALPHA)
state->trans = MSG_ReadByte();
else
state->trans = base->trans;
if (bits & RMQU_SCALE)
state->scale = MSG_ReadByte();
if (bits & FITZU_FRAME2)
state->frame |= MSG_ReadByte() << 8;
state->frame = (state->frame & 0xff) | (MSG_ReadByte() << 8);
if (bits & FITZU_MODEL2)
state->modelindex |= MSG_ReadByte() << 8;
state->modelindex = (state->modelindex & 0xff) | (MSG_ReadByte() << 8);
if (bits & FITZU_LERPFINISH)
MSG_ReadByte();
@ -1479,41 +1459,19 @@ void CLNQ_ParseEntity(unsigned int bits)
else
{
if (bits & DPU_ALPHA)
i = MSG_ReadByte();
else
i = -1;
#ifdef PEXT_TRANS
if (i == -1)
state->trans = base->trans;
else
state->trans = i;
#endif
state->trans = MSG_ReadByte();
if (bits & DPU_SCALE)
i = MSG_ReadByte();
else
i = -1;
#ifdef PEXT_SCALE
if (i == -1)
state->scale = base->scale;
else
state->scale = i;
#endif
state->scale = MSG_ReadByte();
if (bits & DPU_EFFECTS2)
state->effects |= MSG_ReadByte() << 8;
if (bits & DPU_GLOWSIZE)
state->glowsize = MSG_ReadByte();
else
state->glowsize = base->glowsize;
if (bits & DPU_GLOWCOLOR)
state->glowcolour = MSG_ReadByte();
else
state->glowcolour = base->glowcolour;
if (bits & DPU_COLORMOD)
{
@ -1522,12 +1480,6 @@ void CLNQ_ParseEntity(unsigned int bits)
state->colormod[1] = (qbyte)(((i >> 2) & 7) * (32.0f / 7.0f));
state->colormod[2] = (qbyte)((i & 3) * (32.0f / 3.0f));
}
else
{
state->colormod[0] = base->colormod[0];
state->colormod[1] = base->colormod[1];
state->colormod[2] = base->colormod[2];
}
if (bits & DPU_FRAME2)
state->frame |= MSG_ReadByte() << 8;
@ -3333,7 +3285,7 @@ void CL_ParsePlayerinfo (void)
int num;
num = MSG_ReadByte();
if (cl.worldmodel->fromgame != fg_quake)
if (!cl.worldmodel || cl.worldmodel->fromgame != fg_quake)
{
VectorScale(state->szmins, num/56.0f, state->szmins);
VectorScale(state->szmaxs, num/56.0f, state->szmaxs);
@ -4024,7 +3976,7 @@ void CL_SetSolidEntities (void)
{
case 0:
break;
case -16:
case Q1CONTENTS_LADDER:
pent->nonsolid = true;
pent->forcecontentsmask = FTECONTENTS_LADDER;
break;

View file

@ -1810,10 +1810,8 @@ void CL_InitInput (void)
Cmd_AddCommand (vahunk("+p%i", sp+1), CL_Split_f);
Cmd_AddCommand (vahunk("-p%i", sp+1), CL_Split_f);
/*default mlook to pressed, unless on android where we expect a touch-screen and wouldn't be able to move forwards*/
#ifndef ANDROID
/*default mlook to pressed, (on android we split the two sides of the screen)*/
in_mlook.state[sp] = 1;
#endif
}
/*then alternative arged ones*/

View file

@ -265,7 +265,14 @@ char soundlist_name[] =
void CL_MakeActive(char *gamename)
{
extern int fs_finds;
if (fs_finds)
{
Con_DPrintf("%i additional FS searches\n", fs_finds);
fs_finds = 0;
}
cls.state = ca_active;
S_Purge(true);
if (VID_SetWindowCaption)
VID_SetWindowCaption(va("FTE %s: %s", gamename, cls.servername));
@ -1028,6 +1035,7 @@ void CL_ClearState (void)
CL_AllowIndependantSendCmd(false); //model stuff could be a problem.
S_StopAllSounds (true);
S_UntouchAll();
S_ResetFailedLoad();
Cvar_ApplyLatches(CVAR_SERVEROVERRIDE);
@ -1644,6 +1652,9 @@ void CL_CheckServerInfo(void)
else
cl.fpd = atoi(Info_ValueForKey(cl.serverinfo, "fpd"));
cl.gamespeed = atof(Info_ValueForKey(cl.serverinfo, "*gamespeed"))/100.f;
if (cl.gamespeed < 0.1)
cl.gamespeed = 1;
s = Info_ValueForKey(cl.serverinfo, "status");
oldstate = cl.matchstate;
@ -1700,10 +1711,6 @@ void CL_FullServerinfo_f (void)
}
CL_CheckServerInfo();
cl.gamespeed = atof(Info_ValueForKey(cl.serverinfo, "*gamespeed"))/100.f;
if (cl.gamespeed < 0.1)
cl.gamespeed = 1;
cl.csqcdebug = atoi(Info_ValueForKey(cl.serverinfo, "*csqcdebug"));
}

View file

@ -3602,7 +3602,7 @@ void CL_ParseStartSoundPacket(void)
if (!sound_num)
S_StopSound(ent, channel);
else
S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation, 0);
S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation, 0, 0);
}
@ -3680,11 +3680,11 @@ void CLQ2_ParseStartSoundPacket(void)
*skin = '\0';
if (*model)
{
S_StartSound (ent, channel, S_PrecacheSound(va("players/%s/%s", model, cl.sound_precache[sound_num]->name+1)), pos, volume, attenuation, 0);
S_StartSound (ent, channel, S_PrecacheSound(va("players/%s/%s", model, cl.sound_precache[sound_num]->name+1)), pos, volume, attenuation, 0, 0);
return;
}
}
S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume, attenuation, 0);
S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume, attenuation, 0, 0);
}
#endif
@ -3750,7 +3750,7 @@ void CLNQ_ParseStartSoundPacket(void)
if (!sound_num)
S_StopSound(ent, channel);
else
S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation, pitchadj);
S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation, 0, pitchadj);
}
if (ent == cl.playernum[0]+1)
@ -4021,7 +4021,7 @@ void CL_ServerInfo (void)
Con_DPrintf("SERVERINFO: %s=%s\n", key, value);
Info_SetValueForKey (cl.serverinfo, key, value, MAX_SERVERINFO_STRING);
Info_SetValueForStarKey (cl.serverinfo, key, value, MAX_SERVERINFO_STRING);
CL_CheckServerInfo();
}
@ -5225,6 +5225,7 @@ void CLQW_ParseServerMessage (void)
case svcfte_setangledelta:
for (i=0 ; i<3 ; i++)
cl.viewangles[destsplit][i] += MSG_ReadAngle16 ();
VectorCopy (cl.viewangles[destsplit], cl.simangles[destsplit]);
break;
case svc_setangle:
if (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)
@ -5248,6 +5249,8 @@ void CLQW_ParseServerMessage (void)
cl.fixangle[destsplit]=true;
for (i=0 ; i<3 ; i++)
cl.viewangles[destsplit][i] = cl.fixangles[destsplit][i] = MSG_ReadAngle ();
VectorCopy (cl.viewangles[destsplit], cl.simangles[destsplit]);
// cl.viewangles[PITCH] = cl.viewangles[ROLL] = 0;
break;
@ -5413,6 +5416,7 @@ void CLQW_ParseServerMessage (void)
cl.simorg[destsplit][i] = MSG_ReadCoord ();
for (i=0 ; i<3 ; i++)
cl.simangles[destsplit][i] = MSG_ReadAngle ();
VectorCopy (cl.simangles[destsplit], cl.fixangles[destsplit]);
VectorClear (cl.simvel[destsplit]);
break;
@ -5420,6 +5424,7 @@ void CLQW_ParseServerMessage (void)
if (!cl.intermission)
for (i = 0; i < MAX_SPLITS; i++)
cl.simorg[i][2] += cl.viewheight[i];
VectorCopy (cl.fixangles[destsplit], cl.simangles[destsplit]);
cl.intermission = 2;
cl.completed_time = cl.gametime;
@ -6209,6 +6214,10 @@ void CLNQ_ParseServerMessage (void)
case svc_sound:
CLNQ_ParseStartSoundPacket();
break;
case svc_stopsound:
i = MSG_ReadShort();
S_StopSound(i>>3, i&7);
break;
case svc_temp_entity:
CL_ParseTEnt (true);

View file

@ -796,6 +796,9 @@ void CL_PlayerFrameUpdated(player_state_t *plstate, entity_state_t *state, int s
plstate->pm_type = pmtype;
VectorCopy(state->origin, plstate->origin);
plstate->command.angles[0] = state->angles[0] * -3 *65536/360.0;
plstate->command.angles[1] = state->angles[1] * 65536/360.0;
plstate->command.angles[2] = state->angles[2] * 65536/360.0;
VectorScale(state->u.q1.velocity, 1/8.0, plstate->velocity);
plstate->messagenum = sequence;
@ -894,7 +897,7 @@ void CL_PredictMovePNum (int pnum)
if (cl.paused && !(cls.demoplayback!=DPB_MVD && cls.demoplayback!=DPB_EZTV) && (!cl.spectator || !autocam[pnum]))
return;
if (cl.intermission && cl.intermission != 3 && cls.protocol == CP_QUAKEWORLD)
if (cl.intermission==1 && cls.protocol == CP_QUAKEWORLD)
{
cl.crouch[pnum] = 0;
return;

View file

@ -1467,6 +1467,13 @@ void SCR_DrawLoading (void)
//int mtype = M_GameType(); //unused variable
y = vid.height/2;
if (*levelshotname)
{
pic = R2D_SafeCachePic (levelshotname);
R2D_ImageColours(1, 1, 1, 1);
R2D_ScalePic (0, 0, vid.width, vid.height, pic);
}
qdepth = COM_FDepthFile("gfx/loading.lmp", true);
h2depth = COM_FDepthFile("gfx/menu/loading.lmp", true);
@ -1563,6 +1570,7 @@ void SCR_DrawLoading (void)
y = 104;
}
}
R2D_ImageColours(1, 1, 1, 1);
if (cl.downloadlist || cls.downloadmethod)
{
@ -1669,6 +1677,7 @@ void SCR_ImageName (char *mapname)
GL_BeginRendering ();
SCR_DrawLoading();
SCR_SetUpToDrawConsole();
if (key_dest == key_console || !*levelshotname)
SCR_DrawConsole(!!*levelshotname);
GL_EndRendering();
scr_drawloading = false;

View file

@ -898,7 +898,7 @@ void CL_ParseTEnt (void)
if (P_RunParticleEffectType(pos, NULL, 1, pt_wizspike))
P_RunParticleEffect (pos, vec3_origin, 20, 30);
S_StartSound (-2, 0, cl_sfx_wizhit, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_wizhit, pos, 1, 1, 0, 0);
break;
case TE_KNIGHTSPIKE: // spike hitting wall
@ -911,7 +911,7 @@ void CL_ParseTEnt (void)
if (P_RunParticleEffectType(pos, NULL, 1, pt_knightspike))
P_RunParticleEffect (pos, vec3_origin, 226, 20);
S_StartSound (-2, 0, cl_sfx_knighthit, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_knighthit, pos, 1, 1, 0, 0);
break;
case TEDP_SPIKEQUAD:
@ -928,16 +928,16 @@ void CL_ParseTEnt (void)
P_RunParticleEffect (pos, vec3_origin, 0, 10);
if ( rand() % 5 )
S_StartSound (-2, 0, cl_sfx_tink1, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_tink1, pos, 1, 1, 0, 0);
else
{
rnd = rand() & 3;
if (rnd == 1)
S_StartSound (-2, 0, cl_sfx_ric1, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric1, pos, 1, 1, 0, 0);
else if (rnd == 2)
S_StartSound (-2, 0, cl_sfx_ric2, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric2, pos, 1, 1, 0, 0);
else
S_StartSound (-2, 0, cl_sfx_ric3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric3, pos, 1, 1, 0, 0);
}
break;
case TE_SPIKE: // spike hitting wall
@ -953,16 +953,16 @@ void CL_ParseTEnt (void)
P_RunParticleEffect (pos, vec3_origin, 0, 10);
if ( rand() % 5 )
S_StartSound (-2, 0, cl_sfx_tink1, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_tink1, pos, 1, 1, 0, 0);
else
{
rnd = rand() & 3;
if (rnd == 1)
S_StartSound (-2, 0, cl_sfx_ric1, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric1, pos, 1, 1, 0, 0);
else if (rnd == 2)
S_StartSound (-2, 0, cl_sfx_ric2, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric2, pos, 1, 1, 0, 0);
else
S_StartSound (-2, 0, cl_sfx_ric3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric3, pos, 1, 1, 0, 0);
}
break;
case TEDP_SUPERSPIKEQUAD: // super spike hitting wall
@ -980,16 +980,16 @@ void CL_ParseTEnt (void)
P_RunParticleEffect (pos, vec3_origin, 0, 20);
if ( rand() % 5 )
S_StartSound (-2, 0, cl_sfx_tink1, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_tink1, pos, 1, 1, 0, 0);
else
{
rnd = rand() & 3;
if (rnd == 1)
S_StartSound (-2, 0, cl_sfx_ric1, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric1, pos, 1, 1, 0, 0);
else if (rnd == 2)
S_StartSound (-2, 0, cl_sfx_ric2, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric2, pos, 1, 1, 0, 0);
else
S_StartSound (-2, 0, cl_sfx_ric3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric3, pos, 1, 1, 0, 0);
}
break;
case TE_SUPERSPIKE: // super spike hitting wall
@ -1006,16 +1006,16 @@ void CL_ParseTEnt (void)
P_RunParticleEffect (pos, vec3_origin, 0, 20);
if ( rand() % 5 )
S_StartSound (-2, 0, cl_sfx_tink1, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_tink1, pos, 1, 1, 0, 0);
else
{
rnd = rand() & 3;
if (rnd == 1)
S_StartSound (-2, 0, cl_sfx_ric1, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric1, pos, 1, 1, 0, 0);
else if (rnd == 2)
S_StartSound (-2, 0, cl_sfx_ric2, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric2, pos, 1, 1, 0, 0);
else
S_StartSound (-2, 0, cl_sfx_ric3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric3, pos, 1, 1, 0, 0);
}
break;
@ -1035,16 +1035,16 @@ void CL_ParseTEnt (void)
P_RunParticleEffect (pos, vec3_origin, 0, 10);
if ( rand() % 5 )
S_StartSound (-2, 0, cl_sfx_tink1, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_tink1, pos, 1, 1, 0, 0);
else
{
rnd = rand() & 3;
if (rnd == 1)
S_StartSound (-2, 0, cl_sfx_ric1, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric1, pos, 1, 1, 0, 0);
else if (rnd == 2)
S_StartSound (-2, 0, cl_sfx_ric2, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric2, pos, 1, 1, 0, 0);
else
S_StartSound (-2, 0, cl_sfx_ric3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric3, pos, 1, 1, 0, 0);
}
break;
case TE_SUPERBULLET:
@ -1061,16 +1061,16 @@ void CL_ParseTEnt (void)
P_RunParticleEffect (pos, vec3_origin, 0, 20);
if ( rand() % 5 )
S_StartSound (-2, 0, cl_sfx_tink1, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_tink1, pos, 1, 1, 0, 0);
else
{
rnd = rand() & 3;
if (rnd == 1)
S_StartSound (-2, 0, cl_sfx_ric1, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric1, pos, 1, 1, 0, 0);
else if (rnd == 2)
S_StartSound (-2, 0, cl_sfx_ric2, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric2, pos, 1, 1, 0, 0);
else
S_StartSound (-2, 0, cl_sfx_ric3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_ric3, pos, 1, 1, 0, 0);
}
break;
#endif
@ -1105,7 +1105,7 @@ void CL_ParseTEnt (void)
// sound
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0, 0);
// sprite
if (cl_expsprite.ival) // temp hopefully
@ -1145,7 +1145,7 @@ void CL_ParseTEnt (void)
// sound
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0, 0);
// sprite
if (cl_expsprite.ival && !nqprot) // temp hopefully
@ -1184,7 +1184,7 @@ void CL_ParseTEnt (void)
dl->channelfade[2] = 0;
}
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0, 0);
break;
case TEDP_TEI_BIGEXPLOSION:
@ -1215,7 +1215,7 @@ void CL_ParseTEnt (void)
dl->channelfade[2] = 0;
}
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0, 0);
break;
case TE_TAREXPLOSION: // tarbaby explosion
@ -1224,7 +1224,7 @@ void CL_ParseTEnt (void)
pos[2] = MSG_ReadCoord ();
P_RunParticleEffectType(pos, NULL, 1, pt_tarexplosion);
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0, 0);
break;
case TE_LIGHTNING1: // lightning bolts
@ -1989,7 +1989,7 @@ static qbyte splash_color[] = {0x00, 0xe0, 0xb0, 0x50, 0xd0, 0xe0, 0xe8};
#define ATTN_STATIC 1
void Q2S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs)
{
S_StartSoundDelayed(entnum, entchannel, sfx, origin, fvol, attenuation, timeofs);
S_StartSound(entnum, entchannel, sfx, origin, fvol, attenuation, timeofs, 0);
}
void CLQ2_ParseTEnt (void)
{
@ -2052,7 +2052,7 @@ void CLQ2_ParseTEnt (void)
else
P_RunParticleEffect (pos, dir, 0xb0, 40);
//FIXME : replace or remove this sound
S_StartSound (-2, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, 1, 1, 0);
S_StartSound (-2, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, 1, 1, 0, 0);
break;
case Q2TE_SHOTGUN: // bullet hitting wall
@ -2139,7 +2139,7 @@ void CLQ2_ParseTEnt (void)
ex->angles[1] = 0;
ex->angles[0]*=-1;
S_StartSound (-2, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, 1, 1, 0);
S_StartSound (-2, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, 1, 1, 0, 0);
// light
if (r_explosionlight.value)
@ -2197,9 +2197,9 @@ void CLQ2_ParseTEnt (void)
// sound
if (type == Q2TE_GRENADE_EXPLOSION_WATER)
S_StartSound (-2, 0, S_PrecacheSound ("weapons/xpld_wat.wav"), pos, 1, 1, 0);
S_StartSound (-2, 0, S_PrecacheSound ("weapons/xpld_wat.wav"), pos, 1, 1, 0, 0);
else
S_StartSound (-2, 0, S_PrecacheSound ("weapons/grenlx1a.wav"), pos, 1, 1, 0);
S_StartSound (-2, 0, S_PrecacheSound ("weapons/grenlx1a.wav"), pos, 1, 1, 0, 0);
// sprite
@ -2293,9 +2293,9 @@ void CLQ2_ParseTEnt (void)
// sound
if (type == Q2TE_ROCKET_EXPLOSION_WATER)
S_StartSound (-2, 0, S_PrecacheSound ("weapons/xpld_wat.wav"), pos, 1, 1, 0);
S_StartSound (-2, 0, S_PrecacheSound ("weapons/xpld_wat.wav"), pos, 1, 1, 0, 0);
else
S_StartSound (-2, 0, S_PrecacheSound ("weapons/rocklx1a.wav"), pos, 1, 1, 0);
S_StartSound (-2, 0, S_PrecacheSound ("weapons/rocklx1a.wav"), pos, 1, 1, 0, 0);
// sprite
// if (!R_ParticleExplosionHeart(pos))
@ -2469,7 +2469,7 @@ void CLQ2_ParseTEnt (void)
ex->angles[1] = 0;
ex->angles[0]*=-1;
S_StartSound (-2, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, 1, 1, 0);
S_StartSound (-2, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, 1, 1, 0, 0);
// light
if (r_explosionlight.value)
@ -2519,7 +2519,7 @@ void CLQ2_ParseTEnt (void)
ex->angles[1] = 0;
ex->angles[0]*=-1;
S_StartSound (-2, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, 1, 1, 0);
S_StartSound (-2, 0, S_PrecacheSound ("weapons/lashit.wav"), pos, 1, 1, 0, 0);
// light
if (r_explosionlight.value)

View file

@ -981,7 +981,8 @@ void V_SetContentsColor (int contents);
//used directly by csqc
void V_CalcRefdef (int pnum);
void CalcGunAngle (int pnum);
void V_CalcGunPositionAngle (int pnum, float bob);
float V_CalcBob (int pnum, qboolean queryold);
void DropPunchAngle (int pnum);

295
engine/client/in_droid.c Normal file
View file

@ -0,0 +1,295 @@
#include "quakedef.h"
#include <jni.h>
extern qboolean mouse_active;
cvar_t m_filter = CVARF("m_filter", "0", CVAR_ARCHIVE);
cvar_t m_strafeonright = CVARFD("m_strafeonright", "1", CVAR_ARCHIVE, "If 1, touching the right half of the touchscreen will strafe/move, while the left side will turn.");
extern cvar_t _windowed_mouse;
int mousecursor_x, mousecursor_y; /*absolute position*/
extern int mousemove_x, mousemove_y;
static float mouse_x, mouse_y;
static float mousestrafe_x, mousestrafe_y;
static float old_mouse_x, old_mouse_y; /*for smoothing*/
#define EVENTQUEUELENGTH 128
struct eventlist_s
{
enum
{
IEV_KEYDOWN,
IEV_KEYRELEASE,
IEV_MOUSEABS
} type;
int devid;
union
{
struct
{
float x, y;
} mouse;
struct
{
int scancode, unicode;
} keyboard;
};
} eventlist[EVENTQUEUELENGTH];
volatile int events_avail; /*volatile to make sure the cc doesn't try leaving these cached in a register*/
volatile int events_used;
static struct eventlist_s *in_newevent(void)
{
if (events_avail >= events_used + EVENTQUEUELENGTH)
return NULL;
return &eventlist[events_avail & (EVENTQUEUELENGTH-1)];
}
static void in_finishevent(void)
{
events_avail++;
}
#define MAXPOINTERS 8
struct
{
vec2_t oldpos;
vec2_t downpos;
float movedist;
vec2_t move;
int down;
} ptr[MAXPOINTERS];
void IN_Shutdown(void)
{
}
void IN_ReInit()
{
Cvar_Register (&m_filter, "input controls");
Cvar_Register (&m_strafeonright, "input controls");
}
void IN_Init(void)
{
IN_ReInit();
}
/*on android, each 'pointer' is a separate touch location*/
void IN_Commands(void)
{
struct eventlist_s *ev;
while (events_used != events_avail)
{
ev = &eventlist[events_used & (EVENTQUEUELENGTH-1)];
switch(ev->type)
{
case IEV_KEYDOWN:
case IEV_KEYRELEASE:
if (ev->keyboard.scancode == K_MOUSE1 && ev->devid < MAXPOINTERS)
{
if (Key_MouseShouldBeFree())
ptr[ev->devid].down = false;
else
{
if (ev->type == IEV_KEYDOWN)
{
ptr[ev->devid].down = true;
ptr[ev->devid].movedist = 0;
ptr[ev->devid].downpos[0] = ptr[ev->devid].oldpos[0];
ptr[ev->devid].downpos[1] = ptr[ev->devid].oldpos[1];
ptr[ev->devid].move[0] = 0;
ptr[ev->devid].move[1] = 0;
}
else
{
if (ptr[ev->devid].down)
{
if (ptr[ev->devid].movedist < 5)
{
/*if its on the right, make it a mouse2*/
int key = (m_strafeonright.ival && ptr[ev->devid].downpos[0] > vid.pixelwidth/2)?K_MOUSE3:K_MOUSE1;
Key_Event(ev->devid, key, 0, true);
Key_Event(ev->devid, key, 0, false);
}
}
ptr[ev->devid].down = false;
}
break;
}
}
Key_Event(ev->devid, ev->keyboard.scancode, ev->keyboard.unicode, ev->type == IEV_KEYDOWN);
break;
case IEV_MOUSEABS:
/*mouse cursors only really work with one pointer*/
if (ev->devid == 0)
{
mousecursor_x = bound(0, ev->mouse.x, vid.width - 1);
mousecursor_y = bound(0, ev->mouse.y, vid.height - 1);
}
if (ev->devid < MAXPOINTERS)
{
ptr[ev->devid].move[0] += ev->mouse.x - ptr[ev->devid].oldpos[0];
ptr[ev->devid].move[1] += ev->mouse.y - ptr[ev->devid].oldpos[1];
ptr[ev->devid].movedist += fabs(ev->mouse.x - ptr[ev->devid].oldpos[0]) + fabs(ev->mouse.y - ptr[ev->devid].oldpos[1]);
ptr[ev->devid].oldpos[0] = ev->mouse.x;
ptr[ev->devid].oldpos[1] = ev->mouse.y;
}
break;
}
events_used++;
}
}
static void IN_Update(qboolean ingame)
{
int i;
//strafing speed is absolute
mousestrafe_x = 0;
mousestrafe_y = 0;
for (i = 0; i < MAXPOINTERS; i++)
{
/*ignore if no action, to avoid phantom csqc input events*/
if (!ptr[i].down && !ptr[i].move[0] && !ptr[i].move[1])
continue;
if (!CSQC_MousePosition(ptr[i].oldpos[0], ptr[i].oldpos[1], i))
{
if (!CSQC_MouseMove(ptr[i].move[0], ptr[i].move[1], i))
{
if (ptr[i].down && m_strafeonright.ival && ptr[i].downpos[0] > vid.pixelwidth/2 && ingame)
{
mousestrafe_x += ptr[i].oldpos[0] - ptr[i].downpos[0];
mousestrafe_y += ptr[i].oldpos[1] - ptr[i].downpos[1];
}
else
{
mouse_x += ptr[i].move[0];
mouse_y += ptr[i].move[1];
}
}
}
ptr[i].move[0] = 0;
ptr[i].move[1] = 0;
}
}
void IN_Move (float *movements, int pnum)
{
qboolean ingame;
extern int mousecursor_x, mousecursor_y;
if (pnum != 0)
return; //we're lazy today.
ingame = movements != NULL && (key_dest == key_game);
IN_Update(ingame);
if (m_filter.value)
{
mouse_x = (mouse_x + old_mouse_x) * 0.5;
mouse_y = (mouse_y + old_mouse_y) * 0.5;
}
old_mouse_x = mouse_x;
old_mouse_y = mouse_y;
if(in_xflip.value) mouse_x *= -1;
mousemove_x += mouse_x;
mousemove_y += mouse_y;
if (!ingame)
{
mouse_x = mouse_y = 0;
#ifdef VM_UI
UI_MousePosition(mousecursor_x, mousecursor_y);
#endif
}
/*if the look-mouse is set to always strafe instead...*/
if ( (in_strafe.state[pnum] & 1) || (lookstrafe.value && (in_mlook.state[pnum] & 1) ))
{
mousestrafe_x += mouse_x;
mouse_x = 0;
}
if ( (in_strafe.state[pnum] & 1) || !(in_mlook.state[pnum] & 1))
{
mousestrafe_y += mouse_y;
mouse_y = 0;
}
/*handle strafes*/
if (movements)
{
float scale;
scale = m_side.value * sensitivity.value;
movements[1] += mousestrafe_x * scale;
scale = m_forward.value * sensitivity.value;
if ((in_strafe.state[pnum] & 1) && noclip_anglehack)
movements[2] -= mousestrafe_y * scale;
else
movements[0] -= mousestrafe_y * scale;
}
if (in_mlook.state[pnum] & 1)
V_StopPitchDrift (pnum);
/*handle looks*/
cl.viewanglechange[pnum][YAW] -= m_yaw.value * mouse_x * sensitivity.value;
cl.viewanglechange[pnum][PITCH] += m_pitch.value * mouse_y * sensitivity.value;
mouse_x = mouse_y = 0.0;
}
JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_keypress(JNIEnv *env, jobject obj,
jint down, jint keycode, jint unicode)
{
struct eventlist_s *ev = in_newevent();
if (!ev)
return;
ev->type = down?IEV_KEYDOWN:IEV_KEYRELEASE;
ev->devid = 0;
ev->keyboard.scancode = keycode;
ev->keyboard.unicode = unicode;
in_finishevent();
}
JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_motion(JNIEnv *env, jobject obj,
jint act, jint ptrid, jfloat x, jfloat y)
{
struct eventlist_s *ev = in_newevent();
if (!ev)
return;
ev->devid = ptrid;
if (act)
{
ev->type = (act==1)?IEV_KEYDOWN:IEV_KEYRELEASE;
ev->keyboard.scancode = K_MOUSE1;
ev->keyboard.unicode = 0;
}
else
{
ev->type = IEV_MOUSEABS;
ev->mouse.x = x;
ev->mouse.y = y;
}
in_finishevent();
}

View file

@ -55,7 +55,7 @@ cvar_t m_accel = SCVAR("m_accel", "0");
cvar_t m_forcewheel = SCVAR("m_forcewheel", "1");
cvar_t m_forcewheel_threshold = SCVAR("m_forcewheel_threshold", "32");
cvar_t in_dinput = SCVARF("in_dinput","0", CVAR_ARCHIVE);
cvar_t in_builtinkeymap = SCVARF("in_builtinkeymap", "1", CVAR_ARCHIVE);
cvar_t in_builtinkeymap = SCVARF("in_builtinkeymap", "0", CVAR_ARCHIVE);
cvar_t m_accel_noforce = SCVAR("m_accel_noforce", "0");
cvar_t m_threshold_noforce = SCVAR("m_threshold_noforce", "0");
@ -2385,9 +2385,10 @@ void IN_TranslateKeyEvent(WPARAM wParam, LPARAM lParam, qboolean down, int qdevi
extern cvar_t in_builtinkeymap;
int qcode;
int unicode;
extern int keyshift[256];
extern int shift_down;
qcode = MapKey(lParam);
unicode = (qcode < 128)?qcode:0;
if (WinNT && !in_builtinkeymap.value)
{
@ -2400,6 +2401,13 @@ void IN_TranslateKeyEvent(WPARAM wParam, LPARAM lParam, qboolean down, int qdevi
// if (!wchars[1])
unicode = wchars[0];
}
else unicode = 0;
}
else
{
unicode = (qcode < 128)?qcode:0;
if (shift_down && unicode < K_MAX && keyshift[unicode])
unicode = keyshift[unicode];
}
Key_Event (qdeviceid, qcode, unicode, down);

View file

@ -1633,9 +1633,6 @@ void Key_Event (int devid, int key, unsigned int unicode, qboolean down)
return;
}
if (shift_down && unicode < K_MAX && keyshift[unicode])
unicode = keyshift[unicode];
if (!down)
{
switch (key_dest)

View file

@ -178,7 +178,7 @@ extern char chat_buffer[];
extern int chat_bufferlen;
extern qboolean chat_team;
void Key_Event (int pnum, int key, unsigned int unicode, qboolean down);
void Key_Event (int devid, int key, unsigned int unicode, qboolean down);
void Key_Init (void);
void Key_WriteBindings (vfsfile_t *f);
void Key_SetBinding (int keynum, int modifier, char *binding, int cmdlevel);

View file

@ -10,6 +10,8 @@ qboolean bindingactive;
extern cvar_t cl_cursor;
extern cvar_t cl_cursorsize;
extern cvar_t cl_cursorbias;
menu_t *currentmenu;
menu_t *firstmenu;
void Draw_TextBox (int x, int y, int width, int lines)
{
@ -192,7 +194,7 @@ int maxdots;
int mindot;
int dotofs;
void MenuTooltipSplit(menu_t *menu, const char *text)
static void MenuTooltipSplit(menu_t *menu, const char *text)
{
char buf[1024];
char *c, *space;
@ -292,7 +294,7 @@ void MenuTooltipSplit(menu_t *menu, const char *text)
menu->tooltip = mtt;
}
qboolean MI_Selectable(menuoption_t *op)
static qboolean MI_Selectable(menuoption_t *op)
{
switch(op->common.type)
{
@ -331,22 +333,41 @@ qboolean MI_Selectable(menuoption_t *op)
}
}
void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu)
static void M_CheckMouseMove(void)
{
int i;
mpic_t *p;
extern int mousecursor_x, mousecursor_y;
qboolean foundexclusive = false;
int mgt;
menu_t *menu;
menuoption_t *option;
if (omousex != mousecursor_x || omousey != mousecursor_y)
mousemoved = true;
else
mousemoved = false;
omousex = mousecursor_x;
omousey = mousecursor_y;
if (mousemoved)
{
mgt = M_GameType();
while (option)
for (menu = firstmenu; menu; menu = menu->parent)
{
if (menu->exclusive)
{
if (foundexclusive)
continue;
foundexclusive=true;
}
for(option = menu->options; option; option = option = option->common.next)
{
if (mousemoved && !bindingactive && !option->common.ishidden)
{
if (omousex > xpos+option->common.posx-option->common.extracollide && omousex < xpos+option->common.posx+option->common.width)
if (mousecursor_x > menu->xpos+option->common.posx-option->common.extracollide && mousecursor_x < menu->xpos+option->common.posx+option->common.width)
{
if (omousey > ypos+option->common.posy && omousey < ypos+option->common.posy+option->common.height)
if (mousecursor_y > menu->ypos+option->common.posy && mousecursor_y < menu->ypos+option->common.posy+option->common.height)
{
if (MI_Selectable(option))
{
@ -370,6 +391,18 @@ void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu)
}
}
}
}
}
}
}
static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu)
{
int i;
mpic_t *p;
while (option)
{
if (!option->common.ishidden)
switch(option->common.type)
{
@ -602,7 +635,7 @@ void MenuDrawItems(int xpos, int ypos, menuoption_t *option, menu_t *menu)
}
}
void MenuDraw(menu_t *menu)
static void MenuDraw(menu_t *menu)
{
if (menu->event)
menu->event(menu);
@ -1348,9 +1381,6 @@ changed:
}
}
menu_t *currentmenu;
menu_t *firstmenu;
void M_AddMenuFront (menu_t *menu)
{
menu_t *pmenu;
@ -1485,22 +1515,13 @@ void DrawCursor(int prydoncursornum)
Font_DrawChar(x, y, '+' | 0xe000 | CON_WHITEMASK);
Font_EndString(font_conchar);
}
}
void M_Complex_Draw(void)
{
extern int mousecursor_x, mousecursor_y;
menu_t *menu, *cmenu;
qboolean foundexclusive = false;
if (omousex != mousecursor_x || omousey != mousecursor_y)
mousemoved = true;
else
mousemoved = false;
omousex = mousecursor_x;
omousey = mousecursor_y;
if (!firstmenu)
{
key_dest = key_game;
@ -1508,6 +1529,8 @@ void M_Complex_Draw(void)
return;
}
M_CheckMouseMove();
for (menu = firstmenu; menu; )
{
cmenu = menu;
@ -1603,6 +1626,8 @@ void M_Complex_Key(int key, int unicode)
if (!currentmenu)
return; //erm...
M_CheckMouseMove();
if (currentmenu->key)
if (currentmenu->key(key, currentmenu))
return;

View file

@ -219,11 +219,27 @@ qboolean fakecdactive;
qboolean Media_FakeTrack(int i, qboolean loop)
{
char trackname[512];
qboolean found;
if (i > 0 && i <= 999)
{
found = false;
if (!found)
{
sprintf(trackname, "sound/cdtracks/track%03i.ogg", i);
if (COM_FCheckExists(trackname))
found = COM_FCheckExists(trackname);
}
if (!found)
{
sprintf(trackname, "sound/cdtracks/track%03i.mp3", i);
found = COM_FCheckExists(trackname);
}
if (!found)
{
sprintf(trackname, "sound/cdtracks/track%03i.wav", i);
found = COM_FCheckExists(trackname);
}
if (found)
{
Media_Clear();
strcpy(currenttrack.filename, trackname+6);
@ -2940,6 +2956,8 @@ void TTS_Say_f(void)
}
#endif
qboolean S_LoadMP3Sound (sfx_t *s, qbyte *data, int datalen, int sndspeed);
void Media_Init(void)
{
#ifdef _WIN32
@ -2967,6 +2985,8 @@ void Media_Init(void)
#if defined(WINAVI)
Cvar_Register(&capturesoundbits, "AVI capture controls");
Cvar_Register(&capturesoundchannels, "AVI capture controls");
S_RegisterSoundInputPlugin(S_LoadMP3Sound);
#endif
#endif
@ -2980,6 +3000,168 @@ void Media_Init(void)
#ifdef WINAVI
typedef struct
{
HACMSTREAM acm;
unsigned int dstbuffer; /*in frames*/
unsigned int dstcount; /*in frames*/
unsigned int dststart; /*in frames*/
qbyte *dstdata;
unsigned int srcspeed;
unsigned int srcwidth;
unsigned int srcchannels;
unsigned int srcoffset; /*in bytes*/
unsigned int srclen; /*in bytes*/
qbyte srcdata[1];
} mp3decoder_t;
/*must be thread safe*/
sfxcache_t *S_MP3_Locate(sfx_t *sfx, sfxcache_t *buf, int start, int length)
{
int newlen;
if (buf)
{
mp3decoder_t *dec = sfx->decoder.buf;
ACMSTREAMHEADER strhdr;
char buffer[8192];
extern cvar_t snd_linearresample_stream;
int framesz = (dec->srcwidth/8 * dec->srcchannels);
if (dec->dststart > start)
{
/*I don't know where the compressed data is for each sample. acm doesn't have a seek. so reset to start, for music this should be the most common rewind anyway*/
dec->dststart = 0;
dec->dstcount = 0;
dec->srcoffset = 0;
}
if (dec->dstcount > snd_speed*6)
{
int trim = dec->dstcount - snd_speed; //retain a second of buffer in case we have multiple sound devices
// if (trim < 0)
// trim = 0;
/// if (trim > dec->dstcount)
// trim = dec->dstcount;
memmove(dec->dstdata, dec->dstdata + trim*framesz, (dec->dstcount - trim)*framesz);
dec->dststart += trim;
dec->dstcount -= trim;
}
while(start+length >= dec->dststart+dec->dstcount)
{
memset(&strhdr, 0, sizeof(strhdr));
strhdr.cbStruct = sizeof(strhdr);
strhdr.pbSrc = dec->srcdata + dec->srcoffset;
strhdr.cbSrcLength = dec->srclen - dec->srcoffset;
strhdr.pbDst = buffer;
strhdr.cbDstLength = sizeof(buffer);
qacmStreamPrepareHeader(dec->acm, &strhdr, 0);
qacmStreamConvert(dec->acm, &strhdr, ACM_STREAMCONVERTF_BLOCKALIGN);
qacmStreamUnprepareHeader(dec->acm, &strhdr, 0);
dec->srcoffset += strhdr.cbSrcLengthUsed;
if (!strhdr.cbDstLengthUsed)
{
if (strhdr.cbSrcLengthUsed)
continue;
break;
}
newlen = dec->dstcount + (strhdr.cbDstLengthUsed * ((float)snd_speed / dec->srcspeed))/framesz;
if (dec->dstbuffer < newlen+64)
{
dec->dstbuffer = newlen+64 + snd_speed;
dec->dstdata = BZ_Realloc(dec->dstdata, dec->dstbuffer*framesz);
}
SND_ResampleStream(strhdr.pbDst,
dec->srcspeed,
dec->srcwidth/8,
dec->srcchannels,
strhdr.cbDstLengthUsed / framesz,
dec->dstdata+dec->dstcount*framesz,
snd_speed,
dec->srcwidth/8,
dec->srcchannels,
snd_linearresample_stream.ival);
dec->dstcount = newlen;
}
buf->data = dec->dstdata;
buf->length = dec->dstcount;
buf->loopstart = -1;
buf->numchannels = dec->srcchannels;
buf->soundoffset = dec->dststart;
buf->speed = snd_speed;
buf->width = dec->srcwidth/8;
}
return buf;
}
qboolean S_LoadMP3Sound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
{
WAVEFORMATEX pcm_format;
MPEGLAYER3WAVEFORMAT mp3format;
HACMDRIVER drv = NULL;
mp3decoder_t *dec;
char *ext = COM_FileExtension(s->name);
if (stricmp(ext, "mp3"))
return false;
dec = BZF_Malloc(sizeof(*dec) + datalen);
if (!dec)
return false;
memcpy(dec->srcdata, data, datalen);
dec->srclen = datalen;
s->decoder.buf = dec;
s->decoder.abort = NULL;
s->decoder.decodedata = S_MP3_Locate;
dec->dstdata = NULL;
dec->dstcount = 0;
dec->dststart = 0;
dec->dstbuffer = 0;
dec->srcoffset = 0;
dec->srcspeed = 44100;
dec->srcchannels = 2;
dec->srcwidth = 16;
memset (&pcm_format, 0, sizeof(pcm_format));
pcm_format.wFormatTag = WAVE_FORMAT_PCM;
pcm_format.nChannels = dec->srcchannels;
pcm_format.nSamplesPerSec = dec->srcspeed;
pcm_format.nBlockAlign = dec->srcwidth/8*dec->srcchannels;
pcm_format.nAvgBytesPerSec = pcm_format.nSamplesPerSec*dec->srcwidth/8*dec->srcchannels;
pcm_format.wBitsPerSample = dec->srcwidth;
pcm_format.cbSize = 0;
mp3format.wfx.cbSize = MPEGLAYER3_WFX_EXTRA_BYTES;
mp3format.wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3;
mp3format.wfx.nChannels = dec->srcchannels;
mp3format.wfx.nAvgBytesPerSec = 128 * (1024 / 8); // not really used but must be one of 64, 96, 112, 128, 160kbps
mp3format.wfx.wBitsPerSample = 0; // MUST BE ZERO
mp3format.wfx.nBlockAlign = 1; // MUST BE ONE
mp3format.wfx.nSamplesPerSec = dec->srcspeed; // 44.1kHz
mp3format.fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF;
mp3format.nBlockSize = 522; // voodoo value #1
mp3format.nFramesPerBlock = 1; // MUST BE ONE
mp3format.nCodecDelay = 1393; // voodoo value #2
mp3format.wID = MPEGLAYER3_ID_MPEG;
if (!qacmStartup() || 0!=qacmStreamOpen(&dec->acm, drv, (WAVEFORMATEX*)&mp3format, &pcm_format, NULL, 0, 0, 0))
{
Con_Printf("Couldn't init decoder\n");
return false;
}
S_MP3_Locate(s, NULL, 0, 100);
return true;
}
#endif

View file

@ -204,7 +204,7 @@ void M_Audio_StartSound (struct menu_s *menu)
org[0] = mat[0][0] + 2*(mat[1][0]*(info->testsoundsource->common.posx-320/2) + mat[1][0]*(info->testsoundsource->common.posy-200/2));
org[1] = mat[0][1] + 2*(mat[1][1]*(info->testsoundsource->common.posx-320/2) + mat[1][1]*(info->testsoundsource->common.posy-200/2));
org[2] = mat[0][2] + 2*(mat[1][2]*(info->testsoundsource->common.posx-320/2) + mat[1][2]*(info->testsoundsource->common.posy-200/2));
S_StartSound(-2, 0, S_PrecacheSound("player/pain3.wav"), org, 1, 4, 0);
S_StartSound(-2, 0, S_PrecacheSound("player/pain3.wav"), org, 1, 4, 0, 0);
}
}

View file

@ -1388,8 +1388,7 @@ static void QCBUILTIN PF_R_RenderScene(progfuncs_t *prinst, struct globalvars_s
r_refdef.currentplayernum = csqc_lplayernum;
VectorCopy (r_refdef.vieworg, cl.viewent[csqc_lplayernum].origin);
CalcGunAngle(csqc_lplayernum);
V_CalcGunPositionAngle(csqc_lplayernum, V_CalcBob(csqc_lplayernum, true));
R_RenderView();
@ -2422,7 +2421,7 @@ static void QCBUILTIN PF_cs_sound(progfuncs_t *prinst, struct globalvars_s *pr_g
sfx = S_PrecacheSound(sample);
if (sfx)
S_StartSound(-entity->entnum, channel, sfx, entity->v->origin, volume, attenuation, pitchpct);
S_StartSound(-entity->entnum, channel, sfx, entity->v->origin, volume, attenuation, 0, pitchpct);
};
static void QCBUILTIN PF_cs_pointsound(progfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -2446,7 +2445,7 @@ static void QCBUILTIN PF_cs_pointsound(progfuncs_t *prinst, struct globalvars_s
sfx = S_PrecacheSound(sample);
if (sfx)
S_StartSound(0, 0, sfx, origin, volume, attenuation, pitchpct);
S_StartSound(0, 0, sfx, origin, volume, attenuation, 0, pitchpct);
}
static void QCBUILTIN PF_cs_particle(progfuncs_t *prinst, struct globalvars_s *pr_globals)
@ -2832,14 +2831,14 @@ static void QCBUILTIN PF_cl_te_explosion (progfuncs_t *prinst, struct globalvars
R_AddStain(pos, -1, -1, -1, 100);
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0, 0);
}
static void QCBUILTIN PF_cl_te_tarexplosion (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
float *pos = G_VECTOR(OFS_PARM0);
P_RunParticleEffectType(pos, NULL, 1, pt_tarexplosion);
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0, 0);
}
static void QCBUILTIN PF_cl_te_wizspike (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -2847,7 +2846,7 @@ static void QCBUILTIN PF_cl_te_wizspike (progfuncs_t *prinst, struct globalvars_
if (P_RunParticleEffectType(pos, NULL, 1, pt_wizspike))
P_RunParticleEffect (pos, vec3_origin, 20, 30);
S_StartSound (-2, 0, cl_sfx_knighthit, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_knighthit, pos, 1, 1, 0, 0);
}
static void QCBUILTIN PF_cl_te_knightspike (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -2855,7 +2854,7 @@ static void QCBUILTIN PF_cl_te_knightspike (progfuncs_t *prinst, struct globalva
if (P_RunParticleEffectType(pos, NULL, 1, pt_knightspike))
P_RunParticleEffect (pos, vec3_origin, 226, 20);
S_StartSound (-2, 0, cl_sfx_knighthit, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_knighthit, pos, 1, 1, 0, 0);
}
static void QCBUILTIN PF_cl_te_lavasplash (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -2918,7 +2917,7 @@ static void QCBUILTIN PF_cl_te_explosionquad (progfuncs_t *prinst, struct global
dl->channelfade[2] = 0.12;
}
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1, 0, 0);
}
//void(vector org, float radius, float lifetime, vector color) te_customflash
@ -3029,7 +3028,7 @@ static void QCBUILTIN PF_cl_te_explosionrgb (progfuncs_t *prinst, struct globalv
dl->channelfade[2] = 0;
}
S_StartSound (-2, 0, cl_sfx_r_exp3, org, 1, 1, 0);
S_StartSound (-2, 0, cl_sfx_r_exp3, org, 1, 1, 0, 0);
}
static void QCBUILTIN PF_cl_te_particlerain (progfuncs_t *prinst, struct globalvars_s *pr_globals)
{

View file

@ -929,9 +929,18 @@ void QCBUILTIN PF_cl_getmousepos (progfuncs_t *prinst, struct globalvars_s *pr_g
{
float *ret = G_VECTOR(OFS_RETURN);
extern int mousemove_x, mousemove_y;
extern int mousecursor_x, mousecursor_y;
if (Key_MouseShouldBeFree())
{
ret[0] = mousecursor_x;
ret[1] = mousecursor_y;
}
else
{
ret[0] = mousemove_x;
ret[1] = mousemove_y;
}
mousemove_x=0;
mousemove_y=0;

View file

@ -139,6 +139,16 @@ static void DSOUND_Shutdown (soundcardinfo_t *sc)
dshandle_t *dh = sc->handle;
if (!dh)
return;
#ifdef MULTITHREAD
if (sc->thread)
{
sc->selfpainting = false;
Sys_WaitOnThread(sc->thread);
}
#endif
sc->handle = NULL;
#ifdef _IKsPropertySet_
if (dh->EaxKsPropertiesSet)
@ -516,8 +526,23 @@ static void DSOUND_Submit(soundcardinfo_t *sc, int start, int end)
{
}
#ifdef MULTITHREAD
int GetSoundtime(soundcardinfo_t *sc);
static int DSOUND_Thread(void *arg)
{
soundcardinfo_t *sc = arg;
while(sc->selfpainting)
{
S_MixerThread(sc);
/* Quote:
On NT (Win2K and XP) the cursors in SW buffers (and HW buffers on some devices) move in 10ms increments, so calling GetCurrentPosition() every 10ms is ideal.
Calling it more often than every 5ms will cause some perf degradation.
*/
Sleep(9);
}
return 0;
}
#endif
/*
==================
@ -895,6 +920,14 @@ int DSOUND_InitCard (soundcardinfo_t *sc, int cardnum)
}
#endif
#endif
#ifdef MULTITHREAD
sc->selfpainting = true;
sc->thread = Sys_CreateThread(DSOUND_Thread, sc, THREADP_HIGHEST, 0);
if (!sc->thread)
sc->selfpainting = false; /*oh well*/
#endif
return SND_LOADED;
}
int (*pDSOUND_InitCard) (soundcardinfo_t *sc, int cardnum) = &DSOUND_InitCard;

View file

@ -21,14 +21,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h"
void S_Play(void);
void S_PlayVol(void);
void S_SoundList(void);
void S_Update_(soundcardinfo_t *sc);
static void S_Play(void);
static void S_PlayVol(void);
static void S_SoundList_f(void);
static void S_Update_(soundcardinfo_t *sc);
void S_StopAllSounds(qboolean clear);
void S_StopAllSoundsC(void);
static void S_StopAllSounds_f (void);
void S_UpdateCard(soundcardinfo_t *sc);
static void S_UpdateCard(soundcardinfo_t *sc);
static void S_ClearBuffer (soundcardinfo_t *sc);
// =======================================================================
// Internal sound data & structures
@ -59,7 +60,7 @@ int desired_bits = 16;
int sound_started=0;
cvar_t bgmvolume = CVARFD( "musicvolume", "0", CVAR_ARCHIVE,
cvar_t bgmvolume = CVARAFD( "musicvolume", "0", "bgmvolume", CVAR_ARCHIVE,
"Volume level for background music.");
cvar_t volume = CVARFD( "volume", "0.7", CVAR_ARCHIVE,
"Main volume level for all engine sound.");
@ -101,6 +102,8 @@ cvar_t snd_playersoundvolume = CVARAFD( "s_localvolume", "1",
"snd_localvolume", 0,
"Sound level for sounds local or originating from the player such as firing and pain sounds."); //sugested by crunch
cvar_t snd_playbackrate = CVARFD( "snd_playbackrate", "1", CVAR_CHEAT, "Debugging cvar that changes the playback rate of all new sounds.");
cvar_t snd_linearresample = CVARAF( "s_linearresample", "1",
"snd_linearresample", 0);
cvar_t snd_linearresample_stream = CVARAF( "s_linearresample_stream", "0",
@ -124,7 +127,24 @@ cvar_t cl_voip_micamp = CVARAFDC("cl_voip_micamp", "2", NULL, CVAR_ARCHIVE, "Amp
#endif
extern vfsfile_t *rawwritefile;
#ifdef MULTITHREAD
void *mixermutex;
void S_LockMixer(void)
{
Sys_LockMutex(mixermutex);
}
void S_UnlockMixer(void)
{
Sys_UnlockMutex(mixermutex);
}
#else
void S_LockMixer(void)
{
}
void S_UnlockMixer(void)
{
}
#endif
void S_AmbientOff (void)
{
@ -871,13 +891,12 @@ void SNDDMA_SetUnderWater(qboolean underwater)
//so that the video code can call it directly without flushing the models it's just loaded.
void S_DoRestart (void)
{
S_StopAllSounds (true);
S_Shutdown();
if (nosound.ival)
return;
S_StopAllSounds (true);
S_Shutdown();
sound_started = 0;
S_Startup();
ambient_sfx[AMBIENT_WATER] = S_PrecacheSound ("ambience/water1.wav");
@ -888,8 +907,6 @@ void S_DoRestart (void)
void S_Restart_f (void)
{
Cache_Flush();//forget the old sounds.
S_DoRestart();
}
@ -1020,8 +1037,8 @@ void S_Init (void)
Cmd_AddCommand("play", S_Play);
Cmd_AddCommand("play2", S_Play);
Cmd_AddCommand("playvol", S_PlayVol);
Cmd_AddCommand("stopsound", S_StopAllSoundsC);
Cmd_AddCommand("soundlist", S_SoundList);
Cmd_AddCommand("stopsound", S_StopAllSounds_f);
Cmd_AddCommand("soundlist", S_SoundList_f);
Cmd_AddCommand("soundinfo", S_SoundInfo_f);
Cmd_AddCommand("snd_restart", S_Restart_f);
@ -1044,6 +1061,7 @@ void S_Init (void)
Cvar_Register(&snd_speakers, "Sound controls");
Cvar_Register(&snd_buffersize, "Sound controls");
Cvar_Register(&snd_samplebits, "Sound controls");
Cvar_Register(&snd_playbackrate, "Sound controls");
#ifdef VOICECHAT
Cvar_Register(&cl_voip_send, "Voice Chat");
@ -1067,6 +1085,10 @@ void S_Init (void)
Cvar_Register(&snd_linearresample, "Sound controls");
Cvar_Register(&snd_linearresample_stream, "Sound controls");
#ifdef MULTITHREAD
mixermutex = Sys_CreateMutex();
#endif
#ifdef AVAIL_OPENAL
OpenAL_CvarInit();
#endif
@ -1164,6 +1186,7 @@ void S_Shutdown(void)
}
sound_started = 0;
S_Purge(false);
}
@ -1175,6 +1198,7 @@ void S_Shutdown(void)
==================
S_FindName
also touches it
==================
*/
sfx_t *S_FindName (char *name)
@ -1192,6 +1216,7 @@ sfx_t *S_FindName (char *name)
for (i=0 ; i < num_sfx ; i++)
if (!Q_strcmp(known_sfx[i].name, name))
{
known_sfx[i].touched = true;
return &known_sfx[i];
}
@ -1200,12 +1225,45 @@ sfx_t *S_FindName (char *name)
sfx = &known_sfx[i];
strcpy (sfx->name, name);
known_sfx[i].touched = true;
num_sfx++;
return sfx;
}
void S_Purge(qboolean retaintouched)
{
sfx_t *sfx;
int i;
S_LockMixer();
for (i=0 ; i < num_sfx ; i++)
{
sfx = &known_sfx[i];
/*don't purge the file if its still relevent*/
if (retaintouched && sfx->touched)
continue;
/*nothing to do if there's no data within*/
if (!sfx->decoder.buf)
continue;
/*stop the decoder first*/
if (sfx->decoder.abort)
sfx->decoder.abort(sfx);
/*if there's any data associated still, kill it. if present, it should be a single sfxcache_t (with data in same alloc)*/
if (sfx->decoder.buf)
{
BZ_Free(sfx->decoder.buf);
sfx->decoder.buf = NULL;
}
}
S_UnlockMixer();
}
void S_ResetFailedLoad(void)
{
int i;
@ -1213,6 +1271,12 @@ void S_ResetFailedLoad(void)
known_sfx[i].failedload = false;
}
void S_UntouchAll(void)
{
int i;
for (i=0 ; i < num_sfx ; i++)
known_sfx[i].touched = false;
}
/*
==================
@ -1222,13 +1286,10 @@ S_TouchSound
*/
void S_TouchSound (char *name)
{
sfx_t *sfx;
if (!sound_started)
return;
sfx = S_FindName (name);
Cache_Check (&sfx->cache);
S_FindName (name);
}
/*
@ -1264,19 +1325,19 @@ SND_PickChannel
channel_t *SND_PickChannel(soundcardinfo_t *sc, int entnum, int entchannel)
{
int ch_idx;
int first_to_die;
int life_left;
int oldestpos;
int oldest;
// Check for replacement sound, or find the best one to replace
first_to_die = -1;
life_left = 0x7fffffff;
oldest = -1;
oldestpos = -1;
for (ch_idx=DYNAMIC_FIRST; ch_idx < DYNAMIC_STOP ; ch_idx++)
{
if (entchannel != 0 // channel 0 never overrides
&& sc->channel[ch_idx].entnum == entnum
&& (sc->channel[ch_idx].entchannel == entchannel || entchannel == -1))
{ // always override sound from same entity
first_to_die = ch_idx;
oldest = ch_idx;
break;
}
@ -1284,22 +1345,27 @@ channel_t *SND_PickChannel(soundcardinfo_t *sc, int entnum, int entchannel)
if (sc->channel[ch_idx].entnum == cl.playernum[0]+1 && entnum != cl.playernum[0]+1 && sc->channel[ch_idx].sfx)
continue;
if (sc->channel[ch_idx].end < life_left)
if (!sc->channel[ch_idx].sfx)
{
life_left = sc->channel[ch_idx].end;
first_to_die = ch_idx;
oldestpos = 0x7fffffff;
oldest = ch_idx;
}
else if (sc->channel[ch_idx].pos > oldestpos)
{
oldestpos = sc->channel[ch_idx].pos;
oldest = ch_idx;
}
}
if (first_to_die == -1)
if (oldest == -1)
return NULL;
if (sc->channel[first_to_die].sfx)
sc->channel[first_to_die].sfx = NULL;
if (sc->channel[oldest].sfx)
sc->channel[oldest].sfx = NULL;
if (sc->total_chans <= first_to_die)
sc->total_chans = first_to_die+1;
return &sc->channel[first_to_die];
if (sc->total_chans <= oldest)
sc->total_chans = oldest+1;
return &sc->channel[oldest];
}
/*
@ -1355,10 +1421,9 @@ void SND_Spatialize(soundcardinfo_t *sc, channel_t *ch)
// Start a sound effect
// =======================================================================
void S_StartSoundCard(soundcardinfo_t *sc, int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, int startpos, float pitchadj)
static void S_StartSoundCard(soundcardinfo_t *sc, int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, int startpos, float pitchadj)
{
channel_t *target_chan, *check;
sfxcache_t *scache;
int vol;
int ch_idx;
int skip;
@ -1375,6 +1440,8 @@ void S_StartSoundCard(soundcardinfo_t *sc, int entnum, int entchannel, sfx_t *sf
if (pitchadj <= 0)
pitchadj = 100;
pitchadj *= snd_playbackrate.value * (cls.state?cl.gamespeed:1);
vol = fvol*255;
// pick a channel to play on
@ -1402,22 +1469,17 @@ void S_StartSoundCard(soundcardinfo_t *sc, int entnum, int entchannel, sfx_t *sf
return; // not audible at all
// new channel
scache = S_LoadSound (sfx);
if (!scache)
if (!S_LoadSound (sfx))
{
target_chan->sfx = NULL;
return; // couldn't load the sound's data
}
if (scache->length > snd_speed*20 && !ruleset_allow_overlongsounds.ival)
{
Con_DPrintf("Shortening over-long sound effect\n");
startpos = scache->length - snd_speed*10;
}
target_chan->sfx = sfx;
target_chan->rate = ((1<<PITCHSHIFT) * pitchadj) / 100; /*pitchadj is a percentage*/
if (target_chan->rate < 1) /*make sure the rate won't crash us*/
target_chan->rate = 1;
target_chan->pos = startpos*target_chan->rate;
target_chan->end = sc->paintedtime + ((scache->length - startpos)<<PITCHSHIFT)/target_chan->rate;
target_chan->looping = false;
// if an identical sound has also been started this frame, offset the pos
@ -1430,10 +1492,7 @@ void S_StartSoundCard(soundcardinfo_t *sc, int entnum, int entchannel, sfx_t *sf
if (check->sfx == sfx && !check->pos)
{
skip = rand () % (int)(0.1*sc->sn.speed);
if (skip >= target_chan->end)
skip = target_chan->end - 1;
target_chan->pos += skip*target_chan->rate;
target_chan->end -= skip;
target_chan->pos -= skip*target_chan->rate;
break;
}
}
@ -1442,26 +1501,17 @@ void S_StartSoundCard(soundcardinfo_t *sc, int entnum, int entchannel, sfx_t *sf
sc->ChannelUpdate(sc, target_chan, true);
}
void S_StartSoundDelayed(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float timeofs)
void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float timeofs, float pitchadj)
{
soundcardinfo_t *sc;
if (!sfx || !*sfx->name) //no named sounds would need specific starting.
return;
S_LockMixer();
for (sc = sndcardinfo; sc; sc = sc->next)
S_StartSoundCard(sc, entnum, entchannel, sfx, origin, fvol, attenuation, -(int)(timeofs * sc->sn.speed), 0);
}
void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float pitchadj)
{
soundcardinfo_t *sc;
if (!sfx || !*sfx->name) //no named sounds would need specific starting.
return;
for (sc = sndcardinfo; sc; sc = sc->next)
S_StartSoundCard(sc, entnum, entchannel, sfx, origin, fvol, attenuation, 0, pitchadj);
S_StartSoundCard(sc, entnum, entchannel, sfx, origin, fvol, attenuation, -(int)(timeofs * sc->sn.speed), pitchadj);
S_UnlockMixer();
}
qboolean S_IsPlayingSomewhere(sfx_t *s)
@ -1477,7 +1527,7 @@ qboolean S_IsPlayingSomewhere(sfx_t *s)
return false;
}
void S_StopSoundCard(soundcardinfo_t *sc, int entnum, int entchannel)
static void S_StopSoundCard(soundcardinfo_t *sc, int entnum, int entchannel)
{
int i;
@ -1486,12 +1536,11 @@ void S_StopSoundCard(soundcardinfo_t *sc, int entnum, int entchannel)
if (sc->channel[i].entnum == entnum
&& (!entchannel || sc->channel[i].entchannel == entchannel))
{
sc->channel[i].end = 0;
sc->channel[i].sfx = NULL;
if (sc->ChannelUpdate)
sc->ChannelUpdate(sc, &sc->channel[i], true);
if (entchannel)
return;
break;
}
}
}
@ -1499,8 +1548,10 @@ void S_StopSoundCard(soundcardinfo_t *sc, int entnum, int entchannel)
void S_StopSound(int entnum, int entchannel)
{
soundcardinfo_t *sc;
S_LockMixer();
for (sc = sndcardinfo; sc; sc = sc->next)
S_StopSoundCard(sc, entnum, entchannel);
S_UnlockMixer();
}
void S_StopAllSounds(qboolean clear)
@ -1510,21 +1561,21 @@ void S_StopAllSounds(qboolean clear)
soundcardinfo_t *sc;
for (sc = sndcardinfo; sc; sc = sc->next)
{
if (!sound_started)
return;
S_LockMixer();
for (sc = sndcardinfo; sc; sc = sc->next)
{
for (i=0 ; i<sc->total_chans ; i++)
if (sc->channel[i].sfx)
{
s = sc->channel[i].sfx;
sc->channel[i].sfx = NULL;
if (s->decoder)
if (s->decoder.abort)
if (!S_IsPlayingSomewhere(s)) //if we aint playing it elsewhere, free it compleatly.
{
s->decoder->abort(s);
s->decoder.abort(s);
}
if (sc->ChannelUpdate)
sc->ChannelUpdate(sc, &sc->channel[i], true);
@ -1537,14 +1588,16 @@ void S_StopAllSounds(qboolean clear)
if (clear)
S_ClearBuffer (sc);
}
S_UnlockMixer();
}
void S_StopAllSoundsC (void)
static void S_StopAllSounds_f (void)
{
S_StopAllSounds (true);
}
void S_ClearBuffer (soundcardinfo_t *sc)
static void S_ClearBuffer (soundcardinfo_t *sc)
{
void *buffer;
@ -1574,12 +1627,13 @@ S_StaticSound
void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
{
channel_t *ss;
sfxcache_t *scache;
soundcardinfo_t *scard;
if (!sfx)
return;
S_LockMixer();
for (scard = sndcardinfo; scard; scard = scard->next)
{
if (scard->total_chans == MAX_CHANNELS)
@ -1588,26 +1642,19 @@ void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
continue;
}
if (!S_LoadSound (sfx))
break;
ss = &scard->channel[scard->total_chans];
scard->total_chans++;
scache = S_LoadSound (sfx);
if (!scache)
return;
if (scache->loopstart == -1)
{
Con_Printf ("Ambient sound %s not looped\n", sfx->name);
scache->loopstart = 0;
}
ss->entnum = -2;
ss->sfx = sfx;
ss->rate = 1<<PITCHSHIFT;
VectorCopy (origin, ss->origin);
ss->master_vol = vol;
ss->dist_mult = (attenuation/64) / sound_nominal_clip_dist;
ss->end = scard->paintedtime + (scache->length<<PITCHSHIFT)/ss->rate;
ss->pos = 0;
ss->looping = true;
SND_Spatialize (scard, ss);
@ -1615,6 +1662,8 @@ void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation)
if (scard->ChannelUpdate)
scard->ChannelUpdate(scard, ss, true);
}
S_UnlockMixer();
}
@ -1637,16 +1686,16 @@ void S_Music_Clear(sfx_t *onlyifsample)
if (onlyifsample && s != onlyifsample)
continue;
sc->channel[i].end = 0;
sc->channel[i].pos = 0;
sc->channel[i].sfx = NULL;
if (s)
if (s->decoder)
if (s->decoder.abort)
if (!S_IsPlayingSomewhere(s)) //if we aint playing it elsewhere, free it compleatly.
{
s->decoder->abort(s);
if (s->cache.data)
Cache_Free(&s->cache);
s->decoder.abort(s);
// if (s->cache.data)
// Cache_Free(&s->cache);
}
}
}
@ -1660,11 +1709,9 @@ void S_Music_Seek(float time)
for (sc = sndcardinfo; sc; sc=sc->next)
{
sc->channel[i].pos += sc->sn.speed*time * sc->channel[i].rate;
sc->channel[i].end += sc->sn.speed*time;
if (sc->channel[i].pos < 0)
{ //clamp to the start of the track
sc->channel[i].end -= sc->channel[i].pos/sc->channel[i].rate;
sc->channel[i].pos=0;
}
//if we seek over the end, ignore it. The sound playing code will spot that.
@ -1696,21 +1743,17 @@ void S_UpdateAmbientSounds (soundcardinfo_t *sc)
if (!chan->sfx)
{
char *nexttrack = Media_NextTrack(i-MUSIC_FIRST);
sfxcache_t *scache;
sfx_t *newmusic;
if (nexttrack && *nexttrack)
{
newmusic = S_PrecacheSound(nexttrack);
scache = S_LoadSound (newmusic);
if (scache)
if (!newmusic->failedload)
{
chan->sfx = newmusic;
chan->rate = 1<<PITCHSHIFT;
chan->pos = 0;
chan->end = sc->paintedtime + ((scache->length+1000)<<PITCHSHIFT)/chan->rate;
chan->vol[0] = chan->vol[1] = chan->vol[2] = chan->vol[3] = chan->vol[4] = chan->vol[5] = chan->master_vol = 100;
}
}
@ -1799,7 +1842,7 @@ void S_GetListenerInfo(float *origin, float *forward, float *right, float *up)
VectorCopy(listener_up, up);
}
void S_UpdateCard(soundcardinfo_t *sc)
static void S_UpdateCard(soundcardinfo_t *sc)
{
int i, j;
int total;
@ -1899,6 +1942,16 @@ void S_UpdateCard(soundcardinfo_t *sc)
}
// mix some sound
if (sc->selfpainting)
return;
if (snd_blocked > 0)
{
if (!sc->inactive_sound)
return;
}
S_Update_(sc);
}
@ -1939,8 +1992,10 @@ void S_Update (void)
{
soundcardinfo_t *sc;
S_LockMixer();
for (sc = sndcardinfo; sc; sc = sc->next)
S_UpdateCard(sc);
S_UnlockMixer();
}
void S_ExtraUpdate (void)
@ -1957,27 +2012,31 @@ void S_ExtraUpdate (void)
if (snd_noextraupdate.ival)
return; // don't pollute timings
S_LockMixer();
for (sc = sndcardinfo; sc; sc = sc->next)
S_Update_(sc);
}
void S_Update_(soundcardinfo_t *sc)
{
int soundtime; /*in pairs*/
unsigned endtime;
int samps;
if (sc->selfpainting)
return;
continue;
if (snd_blocked > 0)
{
if (!sc->inactive_sound)
return;
continue;
}
S_Update_(sc);
}
S_UnlockMixer();
}
static void S_Update_(soundcardinfo_t *sc)
{
int soundtime; /*in pairs*/
unsigned endtime;
int samps;
// Updates DMA time
soundtime = GetSoundtime(sc);
@ -2016,6 +2075,17 @@ void S_Update_(soundcardinfo_t *sc)
sc->Submit(sc, soundtime, endtime);
}
/*
called periodically by dedicated mixer threads.
do any blocking calls AFTER this returns. note that this means you can't use the Submit/unlock method to submit blocking audio.
*/
void S_MixerThread(soundcardinfo_t *sc)
{
S_LockMixer();
S_Update_(sc);
S_UnlockMixer();
}
/*
===============================================================================
@ -2026,7 +2096,6 @@ console functions
void S_Play(void)
{
// static int hash=345;
int i;
char name[256];
sfx_t *sfx;
@ -2042,15 +2111,13 @@ void S_Play(void)
else
Q_strncpyz(name, Cmd_Argv(i), sizeof(name));
sfx = S_PrecacheSound(name);
S_StartSound(cl.playernum[0]+1, -1, sfx, vec3_origin, 1.0, 0.0, 0);
// hash++;
S_StartSound(cl.playernum[0]+1, -1, sfx, vec3_origin, 1.0, 0.0, 0, 0);
i++;
}
}
void S_PlayVol(void)
{
// static int hash=543;
int i;
float vol;
char name[256];
@ -2068,14 +2135,14 @@ void S_PlayVol(void)
Q_strncpy(name, Cmd_Argv(i), sizeof(name));
sfx = S_PrecacheSound(name);
vol = Q_atof(Cmd_Argv(i+1));
S_StartSound(cl.playernum[0]+1, -1, sfx, vec3_origin, vol, 0.0, 0);
// hash;
S_StartSound(cl.playernum[0]+1, -1, sfx, vec3_origin, vol, 0.0, 0, 0);
i+=2;
}
}
void S_SoundList(void)
void S_SoundList_f(void)
{
/*
int i;
sfx_t *sfx;
sfxcache_t *sc;
@ -2084,6 +2151,11 @@ void S_SoundList(void)
total = 0;
for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
{
if (!sfx->decoder)
{
Con_Printf("S( ) : %s\n", sfx->name);
continue;
}
sc = Cache_Check (&sfx->cache);
if (!sc)
continue;
@ -2093,9 +2165,10 @@ void S_SoundList(void)
Con_Printf ("L");
else
Con_Printf (" ");
Con_Printf("(%2db) %6i : %s\n",sc->width*8, size, sfx->name);
Con_Printf("(%2db%2ic) %6i : %s\n",sc->width*8, sc->numchannels, size, sfx->name);
}
Con_Printf ("Total resident: %i\n", total);
*/
}
@ -2114,27 +2187,10 @@ void S_LocalSound (char *sound)
Con_Printf ("S_LocalSound: can't cache %s\n", sound);
return;
}
S_StartSound (-1, -1, sfx, vec3_origin, 1, 1, 0);
S_StartSound (-1, -1, sfx, vec3_origin, 1, 1, 0, 0);
}
void S_ClearPrecache (void)
{
}
void S_BeginPrecaching (void)
{
}
void S_EndPrecaching (void)
{
}
@ -2145,10 +2201,16 @@ void S_EndPrecaching (void)
typedef struct {
sfxdecode_t decoder;
qboolean inuse;
int id;
sfx_t sfx;
sfxcache_t *sfxcache;
int numchannels;
int width;
int length;
void *data;
} streaming_t;
#define MAX_RAW_SOURCES (MAX_CLIENTS+1)
streaming_t s_streamers[MAX_RAW_SOURCES];
@ -2158,6 +2220,23 @@ void S_ClearRaw(void)
memset(s_streamers, 0, sizeof(s_streamers));
}
//returns an sfxcache_t stating where the data is
sfxcache_t *S_Raw_Locate(sfx_t *sfx, sfxcache_t *buf, int start, int length)
{
streaming_t *s = sfx->decoder.buf;
if (buf)
{
buf->data = s->data;
buf->length = s->length;
buf->loopstart = -1;
buf->numchannels = s->numchannels;
buf->soundoffset = 0;
buf->speed = snd_speed;
buf->width = s->width;
}
return buf;
}
//streaming audio. //this is useful when there is one source, and the sound is to be played with no attenuation
void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels, int width)
{
@ -2168,7 +2247,7 @@ void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels,
int spare;
int outsamples;
double speedfactor;
sfxcache_t *newcache;
qbyte *newcache;
streaming_t *s, *free=NULL;
for (s = s_streamers, i = 0; i < MAX_RAW_SOURCES; i++, s++)
{
@ -2185,9 +2264,9 @@ void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels,
{
if (i == MAX_RAW_SOURCES)
return; //wierd, it wasn't even playing.
s->sfxcache->loopstart = -1; //stop mixing it
s->inuse = false;
S_LockMixer();
for (si = sndcardinfo; si; si=si->next)
for (i = 0; i < si->total_chans; i++)
if (si->channel[i].sfx == &s->sfx)
@ -2195,10 +2274,13 @@ void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels,
si->channel[i].sfx = NULL;
break;
}
BZ_Free(s->sfxcache);
BZ_Free(s->data);
S_UnlockMixer();
return;
}
if (i == MAX_RAW_SOURCES) //whoops.
if (i == MAX_RAW_SOURCES || !s->inuse) //whoops.
{
if (i == MAX_RAW_SOURCES)
{
if (!free)
{
@ -2206,32 +2288,33 @@ void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels,
return;
}
s = free;
free->id = sourceid;
free->inuse = true;
free->sfx.cache.fake = true;
strcpy(free->sfx.name, "");
free->sfxcache = BZ_Malloc(sizeof(sfxcache_t));
free->sfx.cache.data = free->sfxcache;
free->sfxcache->speed = snd_speed;
free->sfxcache->numchannels = channels;
free->sfxcache->width = width;
free->sfxcache->loopstart = -1;
free->sfxcache->length = 0;
}
s->sfx.decoder.buf = s;
s->sfx.decoder.decodedata = S_Raw_Locate;
s->numchannels = channels;
s->width = width;
s->data = NULL;
s->length = 0;
s->id = sourceid;
s->inuse = true;
strcpy(s->sfx.name, "raw stream");
// Con_Printf("Added new raw stream\n");
}
if (s->sfxcache->width != width || s->sfxcache->numchannels != channels || s->sfxcache->speed != snd_speed)
S_LockMixer();
if (s->width != width || s->numchannels != channels)
{
s->sfxcache->width = width;
s->sfxcache->numchannels = channels;
s->sfxcache->speed = snd_speed;
s->sfxcache->length = 0;
s->width = width;
s->numchannels = channels;
s->length = 0;
// Con_Printf("Restarting raw stream\n");
}
speedfactor = (double)speed/snd_speed;
outsamples = samples/speedfactor;
oldlength = s->sfxcache->length;
oldlength = s->length;
prepadl = 0x7fffffff;
for (si = sndcardinfo; si; si=si->next) //make sure all cards are playing, and that we still get a prepad if just one is.
@ -2261,7 +2344,7 @@ void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels,
{
if (prepadl < 0)
prepadl = 0;
spare = s->sfxcache->length - prepadl;
spare = s->length - prepadl;
if (spare < 0) //remaining samples since last time
spare = 0;
@ -2272,18 +2355,17 @@ void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels,
}
}
newcache = BZ_Malloc(sizeof(sfxcache_t) + (spare+outsamples) * (s->sfxcache->numchannels) * s->sfxcache->width);
memcpy(newcache, s->sfxcache, sizeof(sfxcache_t));
memcpy(newcache->data, s->sfxcache->data + prepadl * (s->sfxcache->numchannels) * s->sfxcache->width, spare * (s->sfxcache->numchannels) * s->sfxcache->width);
newcache = BZ_Malloc((spare+outsamples) * (s->numchannels) * s->width);
memcpy(newcache, (qbyte*)s->data + prepadl * (s->numchannels) * s->width, spare * (s->numchannels) * s->width);
BZ_Free(s->sfxcache);
s->sfxcache = s->sfx.cache.data = newcache;
BZ_Free(s->data);
s->data = newcache;
newcache->length = spare + outsamples;
s->length = spare + outsamples;
{
extern cvar_t snd_linearresample_stream;
short *outpos = (short *)(newcache->data + spare * (s->sfxcache->numchannels) * s->sfxcache->width);
short *outpos = (short *)((char*)s->data + spare * (s->numchannels) * s->width);
SND_ResampleStream(data,
speed,
width,
@ -2291,32 +2373,36 @@ void S_RawAudio(int sourceid, qbyte *data, int speed, int samples, int channels,
samples,
outpos,
snd_speed,
s->sfxcache->width,
s->sfxcache->numchannels,
s->width,
s->numchannels,
snd_linearresample_stream.ival);
}
s->sfxcache->loopstart = -1;//s->sfxcache->length;
for (si = sndcardinfo; si; si=si->next)
{
for (i = 0; i < si->total_chans; i++)
if (si->channel[i].sfx == &s->sfx)
{
si->channel[i].pos -= prepadl*si->channel[i].rate;
si->channel[i].end += outsamples;
if (si->channel[i].end < si->paintedtime)
{
if (si->channel[i].pos < 0)
si->channel[i].pos = 0;
si->channel[i].end = si->paintedtime + s->sfxcache->length;
}
break;
}
if (i == si->total_chans) //this one wasn't playing.
{
/*slight delay to try to avoid frame rate/etc stops/starts*/
S_StartSoundCard(si, -1, 0, &s->sfx, r_origin, 1, 32767, -snd_speed*0.02, 0);
channel_t *c = SND_PickChannel(si, -1, 0);
c->entnum = -1;
c->entchannel = 0;
c->dist_mult = 0;
c->looping = false;
c->master_vol = 255;
c->pos = 0;
c->rate = 1<<PITCHSHIFT;
c->sfx = &s->sfx;
c->start = 0;
SND_Spatialize(si, c);
}
}
S_UnlockMixer();
}

View file

@ -11,16 +11,22 @@ static soundcardinfo_t *sys_sc = NULL;
//transfer the 'dma' buffer into the buffer it requests, called from somewhere outside the game engine, prolly another thread.
//transfer the 'dma' buffer into the buffer it requests, called from a dedicated sound thread created by the java code.
JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_paintaudio(JNIEnv *env, jclass this, jbyteArray stream, jint len)
{
int offset = 0;
soundcardinfo_t *sc = sys_sc;
int framesz;
// if (!pthread_mutex_lock(&mutex))
{
soundcardinfo_t *sc = sys_sc;
if (sc)
{
int buffersize = sc->sn.samples*(sc->sn.samplebits/8);
int buffersize = sc->sn.samples*sc->sn.samplebits/8;
int curtime = GetSoundtime(sc);
framesz = sc->sn.numchannels * sc->sn.samplebits/8;
S_PaintChannels (sc, curtime + (len / framesz));
if (len > buffersize)
{
@ -30,16 +36,19 @@ JNIEXPORT jint JNICALL Java_com_fteqw_FTEDroidEngine_paintaudio(JNIEnv *env, jcl
if (len + sc->snd_sent%buffersize > buffersize)
{ //buffer will wrap, fill in the rest
(*env)->SetByteArrayRegion(env, stream, offset, buffersize - (sc->snd_sent%buffersize), (char*)sc->sn.buffer + (sc->snd_sent%buffersize));
offset += buffersize - sc->snd_sent%buffersize;
sc->snd_sent += buffersize - sc->snd_sent%buffersize;
offset += buffersize - (sc->snd_sent%buffersize);
sc->snd_sent += buffersize - (sc->snd_sent%buffersize);
len -= buffersize - (sc->snd_sent%buffersize);
if (len < 0) /*this must be impossible, surely?*/
len = 0;
}
//and finish from the start
(*env)->SetByteArrayRegion(env, stream, offset, len, (char*)sc->sn.buffer + (sc->snd_sent%buffersize));
offset += len;
sc->snd_sent += len;
}
else
offset = len; /*so the playback thread ends up blocked properly*/
// pthread_mutex_unlock(&mutex);
}
return offset;
@ -77,7 +86,7 @@ static void Droid_SetUnderWater(soundcardinfo_t *sc, qboolean uw)
{
}
static void Droid_Submit(soundcardinfo_t *sc)
static void Droid_Submit(soundcardinfo_t *sc, int start, int end)
{
}
@ -88,6 +97,7 @@ static int Droid_InitCard (soundcardinfo_t *sc, int cardnum)
// if (!pthread_mutex_lock(&mutex))
{
sc->selfpainting = true;
sc->sn.speed = 11025;
sc->sn.samplebits = 16;
sc->sn.numchannels = 1;

View file

@ -543,7 +543,7 @@ void SND_ResampleStream (void *in, int inrate, int inwidth, int inchannels, int
ResampleSfx
================
*/
void ResampleSfx (sfx_t *sfx, int inrate, int inchannels, int inwidth, int insamps, int inloopstart, qbyte *data)
qboolean ResampleSfx (sfx_t *sfx, int inrate, int inchannels, int inwidth, int insamps, int inloopstart, qbyte *data)
{
extern cvar_t snd_linearresample;
double scale;
@ -562,16 +562,18 @@ void ResampleSfx (sfx_t *sfx, int inrate, int inchannels, int inwidth, int insam
outwidth = inwidth;
len = outsamps * outwidth * inchannels;
sc = Cache_Alloc (&sfx->cache, len + sizeof(sfxcache_t), sfx->name);
sfx->decoder.buf = sc = BZ_Malloc(len + sizeof(sfxcache_t));
if (!sc)
{
return;
return false;
}
sc->numchannels = inchannels;
sc->width = outwidth;
sc->speed = snd_speed;
sc->length = outsamps;
sc->soundoffset = 0;
sc->data = (qbyte*)(sc+1);
if (inloopstart == -1)
sc->loopstart = inloopstart;
else
@ -587,6 +589,8 @@ void ResampleSfx (sfx_t *sfx, int inrate, int inchannels, int inwidth, int insam
sc->width,
sc->numchannels,
snd_linearresample.ival);
return true;
}
//=============================================================================
@ -703,19 +707,19 @@ sfxcache_t *S_LoadDoomSound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
}
#endif
sfxcache_t *S_LoadWavSound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
qboolean S_LoadWavSound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
{
wavinfo_t info;
if (datalen < 4 || strncmp(data, "RIFF", 4))
return NULL;
return false;
info = GetWavinfo (s->name, data, datalen);
if (info.numchannels < 1 || info.numchannels > 2)
{
s->failedload = true;
Con_Printf ("%s has an unsupported quantity of channels.\n",s->name);
return NULL;
return false;
}
if (info.width == 1)
@ -723,12 +727,10 @@ sfxcache_t *S_LoadWavSound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
else if (info.width == 2)
COM_SwapLittleShortBlock((short *)(data + info.dataofs), info.samples*info.numchannels);
ResampleSfx (s, info.rate, info.numchannels, info.width, info.samples, info.loopstart, data + info.dataofs);
return Cache_Check(&s->cache);
return ResampleSfx (s, info.rate, info.numchannels, info.width, info.samples, info.loopstart, data + info.dataofs);
}
sfxcache_t *S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed);
qboolean S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed);
S_LoadSound_t AudioInputPlugins[10] =
{
@ -762,29 +764,21 @@ S_LoadSound
==============
*/
sfxcache_t *S_LoadSound (sfx_t *s)
qboolean S_LoadSound (sfx_t *s)
{
char stackbuf[65536];
char namebuffer[256];
qbyte *data;
sfxcache_t *sc;
int i;
size_t result;
char *name = s->name;
if (s->failedload)
return NULL; //it failed to load once before, don't bother trying again.
return false; //it failed to load once before, don't bother trying again.
// see if still in memory
sc = Cache_Check (&s->cache);
if (sc)
return sc;
s->decoder = NULL;
if (s->decoder.buf)
return true;
if (name[1] == ':' && name[2] == '\\')
{
@ -816,7 +810,7 @@ sfxcache_t *S_LoadSound (sfx_t *s)
else
{
Con_SafePrintf ("Couldn't load %s\n", namebuffer);
return NULL;
return false;
}
}
else
@ -865,7 +859,7 @@ sfxcache_t *S_LoadSound (sfx_t *s)
//FIXME: check to see if queued for download.
Con_DPrintf ("Couldn't load %s\n", namebuffer);
s->failedload = true;
return NULL;
return false;
}
s->failedload = false;
@ -874,10 +868,9 @@ sfxcache_t *S_LoadSound (sfx_t *s)
{
if (AudioInputPlugins[i])
{
sc = AudioInputPlugins[i](s, data, com_filesize, snd_speed);
if (sc)
if (AudioInputPlugins[i](s, data, com_filesize, snd_speed))
{
return sc;
return true;
}
}
}
@ -886,7 +879,7 @@ sfxcache_t *S_LoadSound (sfx_t *s)
Con_Printf ("Format not recognised: %s\n", namebuffer);
s->failedload = true;
return NULL;
return false;
}

View file

@ -117,15 +117,16 @@ void SND_PaintChannelFrom16Stereo (channel_t *ch, sfxcache_t *sc, int count);
void S_PaintChannels(soundcardinfo_t *sc, int endtime)
{
int i, j;
int i;
int end;
channel_t *ch;
sfxcache_t scachebuf;
sfxcache_t *scache;
sfx_t *s;
int ltime, count;
int avail;
unsigned int maxlen = ruleset_allow_overlongsounds.ival?0xffffffffu>>PITCHSHIFT:snd_speed*20;
// sc->rawstart += sc->paintedtime - sc->oldpaintedtime;
// sc->oldpaintedtime = sc->paintedtime;
while (sc->paintedtime < endtime)
{
// if paintbuffer is smaller than DMA buffer
@ -140,67 +141,47 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime)
ch = sc->channel;
for (i=0; i<sc->total_chans ; i++, ch++)
{
if (!ch->sfx)
s = ch->sfx;
if (!s)
continue;
if (!ch->vol[0] && !ch->vol[1] && !ch->vol[2] && !ch->vol[3] && !ch->vol[4] && !ch->vol[5])
continue;
scache = S_LoadSound (ch->sfx);
if (!scache)
continue;
if ((ch->pos>>PITCHSHIFT) > scache->length) //cache was flushed and gamedir changed.
{
ch->pos = scache->length*ch->rate;
ch->end = sc->paintedtime;
}
ltime = sc->paintedtime;
if (ch->sfx->decoder)
{
int len_diff;
soundcardinfo_t *sndc;
#define qmax(x, y) (x>y)?(x):(y)
len_diff = scache->length;
// start = ch->end - scache->length;
// samples = end - start;
#ifdef warningmsg
#pragma warningmsg("pitch fix needed")
#endif
ch->sfx->decoder->decodemore(ch->sfx,
end - (ch->end - scache->length) + 1);
// ch->pos + end-ltime+1);
scache = S_LoadSound (ch->sfx);
if (!scache)
continue;
len_diff = scache->length - len_diff;
for (sndc = sndcardinfo; sndc; sndc=sndc->next)
{
for (j = 0; j < sndc->total_chans; j++)
if (sndc->channel[j].sfx == ch->sfx) //extend all of these.
ch->end += len_diff*ch->rate;
}
}
while (ltime < end)
{ // paint up to end
if (ch->end < end)
count = ch->end - ltime;
{
if (s->decoder.decodedata)
scache = s->decoder.decodedata(s, &scachebuf, ch->pos>>PITCHSHIFT, 1 + (((end - ltime) * ch->rate)>>PITCHSHIFT)); /*1 for luck - balances audio termination below*/
else
count = end - ltime;
scache = s->decoder.buf;
if (!scache)
{
ch->sfx = NULL;
break;
}
// find how many samples till the sample ends (clamp max length)
avail = scache->length;
if (avail > maxlen)
avail = snd_speed*10;
avail = (((int)(scache->soundoffset + avail)<<PITCHSHIFT) - ch->pos) / ch->rate;
// mix the smaller of how much is available or the time left
count = min(avail, end - ltime);
if (avail < 0)
{
Sys_Printf("sound already past end of buffer\n");
avail = 0;
count = 0;
}
if (count > 0)
{
if (ch->pos < 0) //delay the sound a little
if (ch->pos < 0) //sounds with a pos of 0 are delay-start sounds
{
if (count > -ch->pos)
count = -ch->pos;
//don't progress past 0, so it actually starts properly at the right time with no clicks or anything
if (count > (-ch->pos+255)>>PITCHSHIFT)
count = ((-ch->pos+255)>>PITCHSHIFT);
ltime += count;
ch->pos += count*ch->rate;
continue;
@ -233,36 +214,35 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime)
SND_PaintChannelFrom16(ch, scache, count);
}
ltime += count;
ch->pos += ch->rate * count;
}
// if at end of loop, restart
if (ltime >= ch->end)
if (count == avail)
{
if (scache->loopstart >= 0)
if (scache->loopstart != -1) /*some wavs contain a loop offset directly in the sound file, such samples loop even if a non-looping builtin was used*/
{
if (scache->length == scache->loopstart)
if (scache->length <= scache->loopstart)
break;
ch->pos = scache->loopstart*ch->rate;
ch->end = ltime + ((scache->length - scache->loopstart)<<PITCHSHIFT)/ch->rate;
ch->pos &= ~((-1)<<PITCHSHIFT); /*clear out all but the subsample offset*/
ch->pos += scache->loopstart<<PITCHSHIFT;
if (!scache->length)
{
scache->loopstart=-1;
break;
}
}
else if (ch->looping && scache->length)
else if (ch->looping && scache->length) /*(static)channels which are explicitly looping always loop from the start*/
{
/*restart it*/
ch->pos = 0;
ch->end = ltime + ((scache->length)<<PITCHSHIFT)/ch->rate;
}
else
{ // channel just stopped
s = ch->sfx;
ch->sfx = NULL;
if (s->decoder)
if (s->decoder.abort)
{
if (!S_IsPlayingSomewhere(s))
s->decoder->abort(s);
s->decoder.abort(s);
}
break;
}
@ -281,6 +261,7 @@ void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count)
int data;
signed char *sfx;
int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
if (ch->vol[0] > 255)
ch->vol[0] = 255;
@ -292,22 +273,21 @@ void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count)
sfx = (signed char *)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[ch->pos>>PITCHSHIFT];
ch->pos += ch->rate;
data = sfx[pos>>PITCHSHIFT];
pos += ch->rate;
paintbuffer[i].s[0] += ch->vol[0] * data;
paintbuffer[i].s[1] += ch->vol[1] * data;
}
}
else
{
sfx = (signed char *)sc->data + (ch->pos>>PITCHSHIFT);
sfx = (signed char *)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
data = sfx[i];
paintbuffer[i].s[0] += ch->vol[0] * data;
paintbuffer[i].s[1] += ch->vol[1] * data;
}
ch->pos += count<<PITCHSHIFT;
}
}
@ -316,6 +296,7 @@ void SND_PaintChannelFrom8Stereo (channel_t *ch, sfxcache_t *sc, int count)
// int data;
signed char *sfx;
int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
if (ch->vol[0] > 255)
ch->vol[0] = 255;
@ -327,20 +308,19 @@ void SND_PaintChannelFrom8Stereo (channel_t *ch, sfxcache_t *sc, int count)
sfx = (signed char *)sc->data;
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += ch->vol[0] * sfx[(ch->pos>>(PITCHSHIFT-1))&~1];
paintbuffer[i].s[1] += ch->vol[1] * sfx[(ch->pos>>(PITCHSHIFT-1))|1];
ch->pos += ch->rate;
paintbuffer[i].s[0] += ch->vol[0] * sfx[(pos>>(PITCHSHIFT-1))&~1];
paintbuffer[i].s[1] += ch->vol[1] * sfx[(pos>>(PITCHSHIFT-1))|1];
pos += ch->rate;
}
}
else
{
sfx = (signed char *)sc->data + (ch->pos>>PITCHSHIFT)*2;
sfx = (signed char *)sc->data + (pos>>PITCHSHIFT)*2;
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += ch->vol[0] * sfx[(i<<1)];
paintbuffer[i].s[1] += ch->vol[1] * sfx[(i<<1)+1];
}
ch->pos += count<<PITCHSHIFT;
}
}
@ -348,6 +328,7 @@ void SND_PaintChannelFrom8_4Speaker (channel_t *ch, sfxcache_t *sc, int count)
{
signed char *sfx;
int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
if (ch->vol[0] > 255)
ch->vol[0] = 255;
@ -364,8 +345,8 @@ void SND_PaintChannelFrom8_4Speaker (channel_t *ch, sfxcache_t *sc, int count)
sfx = (signed char *)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[ch->pos>>PITCHSHIFT];
ch->pos += ch->rate;
data = sfx[pos>>PITCHSHIFT];
pos += ch->rate;
paintbuffer[i].s[0] += ch->vol[0] * data;
paintbuffer[i].s[1] += ch->vol[1] * data;
paintbuffer[i].s[2] += ch->vol[2] * data;
@ -374,7 +355,7 @@ void SND_PaintChannelFrom8_4Speaker (channel_t *ch, sfxcache_t *sc, int count)
}
else
{
sfx = (signed char *)sc->data + (ch->pos>>PITCHSHIFT);
sfx = (signed char *)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += ch->vol[0] * sfx[i];
@ -382,7 +363,6 @@ void SND_PaintChannelFrom8_4Speaker (channel_t *ch, sfxcache_t *sc, int count)
paintbuffer[i].s[2] += ch->vol[2] * sfx[i];
paintbuffer[i].s[3] += ch->vol[3] * sfx[i];
}
ch->pos += count<<PITCHSHIFT;
}
}
@ -390,6 +370,7 @@ void SND_PaintChannelFrom8_6Speaker (channel_t *ch, sfxcache_t *sc, int count)
{
signed char *sfx;
int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
if (ch->vol[0] > 255)
ch->vol[0] = 255;
@ -410,8 +391,8 @@ void SND_PaintChannelFrom8_6Speaker (channel_t *ch, sfxcache_t *sc, int count)
sfx = (signed char *)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[ch->pos>>PITCHSHIFT];
ch->pos += ch->rate;
data = sfx[pos>>PITCHSHIFT];
pos += ch->rate;
paintbuffer[i].s[0] += ch->vol[0] * data;
paintbuffer[i].s[1] += ch->vol[1] * data;
paintbuffer[i].s[2] += ch->vol[2] * data;
@ -422,7 +403,7 @@ void SND_PaintChannelFrom8_6Speaker (channel_t *ch, sfxcache_t *sc, int count)
}
else
{
sfx = (signed char *)sc->data + (ch->pos>>PITCHSHIFT);
sfx = (signed char *)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += ch->vol[0] * sfx[i];
@ -432,7 +413,6 @@ void SND_PaintChannelFrom8_6Speaker (channel_t *ch, sfxcache_t *sc, int count)
paintbuffer[i].s[4] += ch->vol[4] * sfx[i];
paintbuffer[i].s[5] += ch->vol[5] * sfx[i];
}
ch->pos += count<<PITCHSHIFT;
}
}
@ -440,6 +420,7 @@ void SND_PaintChannelFrom8_8Speaker (channel_t *ch, sfxcache_t *sc, int count)
{
signed char *sfx;
int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
if (ch->vol[0] > 255)
ch->vol[0] = 255;
@ -464,8 +445,8 @@ void SND_PaintChannelFrom8_8Speaker (channel_t *ch, sfxcache_t *sc, int count)
sfx = (signed char *)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[ch->pos>>PITCHSHIFT];
ch->pos += ch->rate;
data = sfx[pos>>PITCHSHIFT];
pos += ch->rate;
paintbuffer[i].s[0] += ch->vol[0] * data;
paintbuffer[i].s[1] += ch->vol[1] * data;
paintbuffer[i].s[2] += ch->vol[2] * data;
@ -478,7 +459,7 @@ void SND_PaintChannelFrom8_8Speaker (channel_t *ch, sfxcache_t *sc, int count)
}
else
{
sfx = (signed char *)sc->data + (ch->pos>>PITCHSHIFT);
sfx = (signed char *)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += ch->vol[0] * sfx[i];
@ -490,7 +471,6 @@ void SND_PaintChannelFrom8_8Speaker (channel_t *ch, sfxcache_t *sc, int count)
paintbuffer[i].s[6] += ch->vol[6] * sfx[i];
paintbuffer[i].s[7] += ch->vol[7] * sfx[i];
}
ch->pos += count<<PITCHSHIFT;
}
}
@ -502,6 +482,7 @@ void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
int leftvol, rightvol;
signed short *sfx;
int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
leftvol = ch->vol[0];
rightvol = ch->vol[1];
@ -512,15 +493,15 @@ void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
sfx = (signed short *)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[ch->pos>>PITCHSHIFT];
ch->pos += ch->rate;
data = sfx[pos>>PITCHSHIFT];
pos += ch->rate;
paintbuffer[i].s[0] += (leftvol * data)>>8;
paintbuffer[i].s[1] += (rightvol * data)>>8;
}
}
else
{
sfx = (signed short *)sc->data + (ch->pos>>PITCHSHIFT);
sfx = (signed short *)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
data = sfx[i];
@ -529,7 +510,6 @@ void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
paintbuffer[i].s[0] += left;
paintbuffer[i].s[1] += right;
}
ch->pos += count<<PITCHSHIFT;
}
}
@ -538,6 +518,7 @@ void SND_PaintChannelFrom16Stereo (channel_t *ch, sfxcache_t *sc, int count)
int leftvol, rightvol;
signed short *sfx;
int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
leftvol = ch->vol[0];
rightvol = ch->vol[1];
@ -548,22 +529,21 @@ void SND_PaintChannelFrom16Stereo (channel_t *ch, sfxcache_t *sc, int count)
sfx = (signed short *)sc->data;
for (i=0 ; i<count ; i++)
{
l = sfx[(ch->pos>>(PITCHSHIFT-1))&~1];
r = sfx[(ch->pos>>(PITCHSHIFT-1))|1];
ch->pos += ch->rate;
l = sfx[(pos>>(PITCHSHIFT-1))&~1];
r = sfx[(pos>>(PITCHSHIFT-1))|1];
pos += ch->rate;
paintbuffer[i].s[0] += (ch->vol[0] * l)>>8;
paintbuffer[i].s[1] += (ch->vol[1] * r)>>8;
}
}
else
{
sfx = (signed short *)sc->data + (ch->pos>>PITCHSHIFT)*2;
sfx = (signed short *)sc->data + (pos>>PITCHSHIFT)*2;
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += (*sfx++ * leftvol) >> 8;
paintbuffer[i].s[1] += (*sfx++ * rightvol) >> 8;
}
ch->pos += count<<PITCHSHIFT;
}
}
@ -572,6 +552,7 @@ void SND_PaintChannelFrom16_4Speaker (channel_t *ch, sfxcache_t *sc, int count)
int vol[4];
signed short *sfx;
int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
vol[0] = ch->vol[0];
vol[1] = ch->vol[1];
@ -584,8 +565,8 @@ void SND_PaintChannelFrom16_4Speaker (channel_t *ch, sfxcache_t *sc, int count)
sfx = (signed short *)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[ch->pos>>PITCHSHIFT];
ch->pos += ch->rate;
data = sfx[pos>>PITCHSHIFT];
pos += ch->rate;
paintbuffer[i].s[0] += (vol[0] * data)>>8;
paintbuffer[i].s[1] += (vol[1] * data)>>8;
paintbuffer[i].s[2] += (vol[2] * data)>>8;
@ -594,7 +575,7 @@ void SND_PaintChannelFrom16_4Speaker (channel_t *ch, sfxcache_t *sc, int count)
}
else
{
sfx = (signed short *)sc->data + ch->pos;
sfx = (signed short *)sc->data + pos;
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += (sfx[i] * vol[0]) >> 8;
@ -602,7 +583,6 @@ void SND_PaintChannelFrom16_4Speaker (channel_t *ch, sfxcache_t *sc, int count)
paintbuffer[i].s[2] += (sfx[i] * vol[2]) >> 8;
paintbuffer[i].s[3] += (sfx[i] * vol[3]) >> 8;
}
ch->pos += count<<PITCHSHIFT;
}
}
@ -611,6 +591,7 @@ void SND_PaintChannelFrom16_6Speaker (channel_t *ch, sfxcache_t *sc, int count)
int vol[6];
signed short *sfx;
int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
vol[0] = ch->vol[0];
vol[1] = ch->vol[1];
@ -625,8 +606,8 @@ void SND_PaintChannelFrom16_6Speaker (channel_t *ch, sfxcache_t *sc, int count)
sfx = (signed short *)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[ch->pos>>PITCHSHIFT];
ch->pos += ch->rate;
data = sfx[pos>>PITCHSHIFT];
pos += ch->rate;
paintbuffer[i].s[0] += (vol[0] * data)>>8;
paintbuffer[i].s[1] += (vol[1] * data)>>8;
paintbuffer[i].s[2] += (vol[2] * data)>>8;
@ -637,7 +618,7 @@ void SND_PaintChannelFrom16_6Speaker (channel_t *ch, sfxcache_t *sc, int count)
}
else
{
sfx = (signed short *)sc->data + (ch->pos>>PITCHSHIFT);
sfx = (signed short *)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += (sfx[i] * vol[0]) >> 8;
@ -647,7 +628,6 @@ void SND_PaintChannelFrom16_6Speaker (channel_t *ch, sfxcache_t *sc, int count)
paintbuffer[i].s[4] += (sfx[i] * vol[4]) >> 8;
paintbuffer[i].s[5] += (sfx[i] * vol[5]) >> 8;
}
ch->pos += count<<PITCHSHIFT;
}
}
@ -656,6 +636,7 @@ void SND_PaintChannelFrom16_8Speaker (channel_t *ch, sfxcache_t *sc, int count)
int vol[8];
signed short *sfx;
int i;
unsigned int pos = ch->pos-(sc->soundoffset<<PITCHSHIFT);
vol[0] = ch->vol[0];
vol[1] = ch->vol[1];
@ -672,8 +653,8 @@ void SND_PaintChannelFrom16_8Speaker (channel_t *ch, sfxcache_t *sc, int count)
sfx = (signed short *)sc->data;
for (i=0 ; i<count ; i++)
{
data = sfx[ch->pos>>PITCHSHIFT];
ch->pos += ch->rate;
data = sfx[pos>>PITCHSHIFT];
pos += ch->rate;
paintbuffer[i].s[0] += (vol[0] * data)>>8;
paintbuffer[i].s[1] += (vol[1] * data)>>8;
paintbuffer[i].s[2] += (vol[2] * data)>>8;
@ -686,7 +667,7 @@ void SND_PaintChannelFrom16_8Speaker (channel_t *ch, sfxcache_t *sc, int count)
}
else
{
sfx = (signed short *)sc->data + (ch->pos>>PITCHSHIFT);
sfx = (signed short *)sc->data + (pos>>PITCHSHIFT);
for (i=0 ; i<count ; i++)
{
paintbuffer[i].s[0] += (sfx[i] * vol[0]) >> 8;
@ -698,6 +679,5 @@ void SND_PaintChannelFrom16_8Speaker (channel_t *ch, sfxcache_t *sc, int count)
paintbuffer[i].s[6] += (sfx[i] * vol[6]) >> 8;
paintbuffer[i].s[7] += (sfx[i] * vol[7]) >> 8;
}
ch->pos += count<<PITCHSHIFT;
}
}

View file

@ -18,18 +18,8 @@
#define oggvorbislibrary VorbisFileBase
struct Library *VorbisFileBase;
#elif defined(_WIN32)
#define WINDOWSDYNAMICLINK
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
HINSTANCE oggvorbislibrary;
#else
#include <dlfcn.h>
void *oggvorbislibrary;
dllhandle_t *oggvorbislibrary;
#endif
#ifdef __MORPHOS__
@ -39,6 +29,7 @@
#define p_ov_comment ov_comment
#define p_ov_pcm_total ov_pcm_total
#define p_ov_read ov_read
#define p_ov_pcm_seek ov_pcm_seek
#else
int (VARGS *p_ov_open_callbacks) (void *datasource, OggVorbis_File *vf, char *initial, long ibytes, ov_callbacks callbacks);
int (VARGS *p_ov_clear)(OggVorbis_File *vf);
@ -47,6 +38,7 @@
ogg_int64_t (VARGS *p_ov_pcm_total)(OggVorbis_File *vf,int i);
long (VARGS *p_ov_read)(OggVorbis_File *vf,char *buffer,int length,
int bigendianp,int word,int sgned,int *bitstream);
int (VARGS *p_ov_pcm_seek)(OggVorbis_File *vf,ogg_int64_t pos);
#endif
@ -55,177 +47,188 @@ typedef struct {
unsigned long length;
unsigned long pos;
int srcspeed;
int srcchannels;
qboolean failed;
sfxcache_t mediasc;
char *mediaaswavdata;
int mediaaswavpos;
int mediaaswavbuflen;
char *mediatemprecode;
int mediatemprecodelen;
char *tempbuffer;
int tempbufferbytes;
char *decodedbuffer;
int decodedbufferbytes;
int decodedbytestart;
int decodedbytecount;
OggVorbis_File vf;
sfx_t *s;
} ovdecoderbuffer_t;
int OV_DecodeSome(sfx_t *s, int minlength);
sfxcache_t *OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf, int start, int length);
void OV_CancelDecoder(sfx_t *s);
qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuffer_t *buffer);
sfxcache_t *S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
qboolean S_LoadOVSound (sfx_t *s, qbyte *data, int datalen, int sndspeed)
{
//char namebuffer[MAX_OSPATH]; //unreferenced
char *name;
ovdecoderbuffer_t *buffer;
//FILE *f; //unreferenced
//qboolean telluser; //unreferenced
//int len; //unreferenced
if (datalen < 4 || strncmp(data, "OggS", 4))
return NULL;
return false;
name = s->name;
if (!s->decoder)
s->decoder = Z_Malloc(sizeof(ovdecoderbuffer_t) + sizeof(sfxdecode_t));
buffer = (ovdecoderbuffer_t*)(s->decoder+1);
buffer = Z_Malloc(sizeof(ovdecoderbuffer_t));
buffer->mediaaswavpos=0;
buffer->mediasc.length=0;
buffer->decodedbytestart = 0;
buffer->decodedbytecount = 0;
buffer->s = s;
s->decoder->buf = buffer;
s->decoder->decodemore = OV_DecodeSome;
s->decoder->abort = OV_CancelDecoder;
s->decoder.buf = buffer;
s->decoder.decodedata = OV_DecodeSome;
s->decoder.abort = OV_CancelDecoder;
if (!OV_StartDecode(data, datalen, buffer))
{
if (buffer->mediaaswavdata)
if (buffer->decodedbuffer)
{
BZ_Free(buffer->mediaaswavdata);
buffer->mediaaswavdata = NULL;
BZ_Free(buffer->decodedbuffer);
buffer->decodedbuffer = NULL;
}
if (buffer->mediatemprecode)
{
BZ_Free(buffer->mediatemprecode);
buffer->mediatemprecode = NULL;
}
Z_Free(s->decoder);
s->decoder=NULL;
buffer->decodedbufferbytes = 0;
buffer->decodedbytestart = 0;
buffer->decodedbytecount = 0;
Z_Free(s->decoder.buf);
s->decoder.buf = NULL;
s->failedload = true;
return NULL;
return false;
}
buffer->mediaaswavpos = sizeof(sfxcache_t);
s->decoder.decodedata(s, NULL, 0, 100);
s->decoder->decodemore(s, 100);
s->cache.fake=true;
return buffer->s->cache.data;
return true;
}
int OV_DecodeSome(sfx_t *s, int minlength)
sfxcache_t *OV_DecodeSome(struct sfx_s *sfx, struct sfxcache_s *buf, int start, int length)
{
extern int snd_speed;
extern cvar_t snd_linearresample_stream;
int bigendianp = bigendian;
int current_section = 0;
sfxcache_t *sc;
ovdecoderbuffer_t *dec = s->decoder->buf;
ovdecoderbuffer_t *dec = sfx->decoder.buf;
int bytesread;
int outspeed = snd_speed;
// Con_Printf("Minlength = %03i ", minlength);
start *= 2*dec->srcchannels;
length *= 2*dec->srcchannels;
for (;;)
{
if (dec->mediaaswavbuflen < dec->mediaaswavpos+minlength+11050) //expand if needed.
if (start < dec->decodedbytestart)
{
/*something rewound, purge clear the buffer*/
dec->decodedbytecount = 0;
dec->decodedbytestart = start;
//check pos
p_ov_pcm_seek(&dec->vf, dec->decodedbytestart);
}
if (start+length <= dec->decodedbytestart + dec->decodedbytecount)
break;
if (dec->decodedbytecount > snd_speed*8)
{
/*everything is okay, but our buffer is getting needlessly large.
keep anything after the 'new' position, but discard all before that
trim shouldn't be able to go negative
*/
unsigned int trim = start - dec->decodedbytestart;
//FIXME: retain an extra half-second for dual+ sound devices running slightly out of sync
memmove(dec->decodedbuffer, dec->decodedbuffer + trim, dec->decodedbytecount - trim);
dec->decodedbytecount -= trim;
dec->decodedbytestart += trim;
}
if (dec->decodedbufferbytes < start+length - dec->decodedbytestart + 128) //expand if needed.
{
// Con_Printf("Expand buffer\n");
dec->mediaaswavbuflen += minlength+22100;
dec->mediaaswavdata = BZ_Realloc(dec->mediaaswavdata, dec->mediaaswavbuflen);
s->cache.data = dec->mediaaswavdata;
s->cache.fake = true;
sc = s->cache.data;
sc->numchannels = dec->mediasc.numchannels;
sc->loopstart = -1;
}
else
sc = s->cache.data;
if (minlength < sc->length)
{
// Con_Printf("No need for decode\n");
//done enough for now, don't whizz through the lot
return 0;
dec->decodedbufferbytes = (start+length - dec->decodedbytestart) + snd_speed;
dec->decodedbuffer = BZ_Realloc(dec->decodedbuffer, dec->decodedbufferbytes);
}
if (snd_speed == dec->srcspeed)
if (outspeed == dec->srcspeed)
{
bytesread = p_ov_read(&dec->vf, dec->mediaaswavdata+dec->mediaaswavpos, dec->mediaaswavbuflen-dec->mediaaswavpos, bigendianp, 2, 1, &current_section);
bytesread = p_ov_read(&dec->vf, dec->decodedbuffer+dec->decodedbytecount, (start+length) - (dec->decodedbytestart+dec->decodedbytecount), bigendianp, 2, 1, &current_section);
if (bytesread <= 0)
{
if (bytesread != 0) //0==eof
{
Con_Printf("ogg decoding failed\n");
return 1;
return NULL;
}
return 0;
break;
}
}
else
{
double scale = dec->srcspeed / (double)snd_speed;
int decodesize = ceil((dec->mediaaswavbuflen-dec->mediaaswavpos) * scale);
if (decodesize > dec->mediatemprecodelen)
double scale = dec->srcspeed / (double)outspeed;
int decodesize = ceil((dec->decodedbufferbytes-dec->decodedbytecount) * scale);
/*round down...*/
decodesize &= ~(2 * dec->srcchannels - 1);
if (decodesize > dec->tempbufferbytes)
{
dec->mediatemprecode = BZ_Realloc(dec->mediatemprecode, decodesize);
dec->mediatemprecodelen = decodesize;
dec->tempbuffer = BZ_Realloc(dec->tempbuffer, decodesize);
dec->tempbufferbytes = decodesize;
}
bytesread = p_ov_read(&dec->vf, dec->mediatemprecode, decodesize, bigendianp, 2, 1, &current_section);
bytesread = p_ov_read(&dec->vf, dec->tempbuffer, decodesize, bigendianp, 2, 1, &current_section);
if (bytesread <= 0)
{
if (bytesread != 0) //0==eof
{
Con_Printf("ogg decoding failed\n");
return 1;
return NULL;
}
return 0;
return NULL;
}
SND_ResampleStream(dec->mediatemprecode,
SND_ResampleStream(dec->tempbuffer,
dec->srcspeed,
2,
dec->mediasc.numchannels,
bytesread / (2 * dec->mediasc.numchannels),
dec->mediaaswavdata+dec->mediaaswavpos,
snd_speed,
dec->srcchannels,
bytesread / (2 * dec->srcchannels),
dec->decodedbuffer+dec->decodedbytecount,
outspeed,
2,
dec->mediasc.numchannels,
dec->srcchannels,
snd_linearresample_stream.ival);
bytesread = (int)floor(bytesread / scale) & ~0x1;
}
dec->mediaaswavpos += bytesread;
dec->decodedbytecount += bytesread;
}
sc->length = (dec->mediaaswavpos-sizeof(sfxcache_t))/(2*(dec->mediasc.numchannels));
dec->mediasc.length = sc->length;
if (minlength<=sc->length)
if (buf)
{
// Con_Printf("Reached length\n");
return 1;
}
buf->data = dec->decodedbuffer;
buf->soundoffset = dec->decodedbytestart / (2 * dec->srcchannels);
buf->length = dec->decodedbytecount;
buf->loopstart = -1;
buf->numchannels = dec->srcchannels;
buf->speed = snd_speed;
buf->width = 2;
}
return buf;
}
void OV_CancelDecoder(sfx_t *s)
{
/*
sfxcache_t *src, *dest;
ovdecoderbuffer_t *dec;
@ -241,14 +244,15 @@ void OV_CancelDecoder(sfx_t *s)
memcpy(dest, src, dec->mediaaswavpos);
BZ_Free(src);
if (dec->mediatemprecode)
if (dec->tempbuffer)
{
BZ_Free(dec->mediatemprecode);
dec->mediatemprecode = NULL;
BZ_Free(dec->tempbuffer);
dec->tempbufferbytes = NULL;
}
Z_Free(s->decoder);
s->decoder = NULL;
*/
//and it's now indistinguisable from a wav
}
@ -305,6 +309,19 @@ static ov_callbacks callbacks = {
qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuffer_t *buffer)
{
static qboolean tried;
static dllfunction_t funcs[] =
{
{(void*)&p_ov_open_callbacks, "ov_open_callbacks"},
{(void*)&p_ov_comment, "ov_comment"},
{(void*)&p_ov_pcm_total, "ov_pcm_total"},
{(void*)&p_ov_clear, "ov_clear"},
{(void*)&p_ov_info, "ov_info"},
{(void*)&p_ov_read, "ov_read"},
{(void*)&p_ov_pcm_seek, "ov_pcm_seek"},
{NULL}
};
static void *libhandle;
if (!oggvorbislibrary && !tried)
#if defined(__MORPHOS__)
{
@ -314,41 +331,19 @@ qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuf
Con_Printf("Unable to open vorbisfile.library version 2\n");
}
}
#elif defined(WINDOWSDYNAMICLINK)
#elif defined(_WIN32)
{
oggvorbislibrary = LoadLibrary("vorbisfile.dll");
oggvorbislibrary = Sys_LoadLibrary("vorbisfile", funcs);
if (!oggvorbislibrary)
oggvorbislibrary = LoadLibrary("libvorbisfile.dll");
oggvorbislibrary = Sys_LoadLibrary("libvorbisfile", funcs);
if (!oggvorbislibrary)
{
Con_Printf("Couldn't load DLL: \"vorbisfile.dll\".\n");
}
else
{
p_ov_open_callbacks = (void *)GetProcAddress(oggvorbislibrary, "ov_open_callbacks");
p_ov_comment = (void *)GetProcAddress(oggvorbislibrary, "ov_comment");
p_ov_pcm_total = (void *)GetProcAddress(oggvorbislibrary, "ov_pcm_total");
p_ov_clear = (void *)GetProcAddress(oggvorbislibrary, "ov_clear");
p_ov_info = (void *)GetProcAddress(oggvorbislibrary, "ov_info");
p_ov_read = (void *)GetProcAddress(oggvorbislibrary, "ov_read");
}
}
#else
{
oggvorbislibrary = dlopen("libvorbisfile.so", RTLD_LOCAL | RTLD_LAZY);
oggvorbislibrary = Sys_LoadLibrary("libvorbisfile", funcs);
if (!oggvorbislibrary)
{
Con_Printf("Couldn't load SO: \"libvorbisfile.so\".\n");
}
else
{
p_ov_open_callbacks = (void *)dlsym(oggvorbislibrary, "ov_open_callbacks");
p_ov_comment = (void *)dlsym(oggvorbislibrary, "ov_comment");
p_ov_pcm_total = (void *)dlsym(oggvorbislibrary, "ov_pcm_total");
p_ov_clear = (void *)dlsym(oggvorbislibrary, "ov_clear");
p_ov_info = (void *)dlsym(oggvorbislibrary, "ov_info");
p_ov_read = (void *)dlsym(oggvorbislibrary, "ov_read");
}
Con_Printf("Couldn't load library: \"libvorbisfile\".\n");
}
#endif
@ -381,8 +376,7 @@ qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuf
return false;
}
buffer->mediasc.numchannels = vi->channels;
buffer->mediasc.loopstart = -1;
buffer->srcchannels = vi->channels;
buffer->srcspeed = vi->rate;
/*
while(*ptr){
@ -394,8 +388,8 @@ qboolean OV_StartDecode(unsigned char *start, unsigned long length, ovdecoderbuf
(long)p_ov_pcm_total(&buffer->vf,-1));
Con_Printf("Encoded by: %s\n\n",p_ov_comment(&buffer->vf,-1)->vendor);
*/ }
buffer->mediatemprecode = NULL;
buffer->mediatemprecodelen = 0;
buffer->tempbuffer = NULL;
buffer->tempbufferbytes = 0;
buffer->start = BZ_Malloc(length);
memcpy(buffer->start, start, length);

View file

@ -40,7 +40,7 @@ typedef struct
typedef struct {
int decodedlen;
int (*decodemore) (struct sfx_s *sfx, int length); //retrurn true when done.
struct sfxcache_s *(*decodedata) (struct sfx_s *sfx, struct sfxcache_s *buf, int start, int length); //retrurn true when done.
void (*abort) (struct sfx_s *sfx); //it's not playing elsewhere. free entirly
void *buf;
} sfxdecode_t;
@ -51,20 +51,21 @@ typedef struct sfx_s
#ifdef AVAIL_OPENAL
unsigned int openal_buffer;
#endif
qboolean failedload; //no more super-spammy
cache_user_t cache;
sfxdecode_t *decoder;
qboolean failedload:1; //no more super-spammy
qboolean touched:1; //if the sound is still relevent
sfxdecode_t decoder;
} sfx_t;
// !!! if this is changed, it much be changed in asm_i386.h too !!!
typedef struct sfxcache_s
{
int length;
int loopstart;
int speed;
int width;
int numchannels;
qbyte data[1]; // variable sized
unsigned int length;
unsigned int loopstart;
unsigned int speed;
unsigned int width;
unsigned int numchannels;
unsigned int soundoffset; //byte index into the sound
qbyte *data; // variable sized
} sfxcache_t;
typedef struct
@ -72,23 +73,23 @@ typedef struct
// qboolean gamealive;
// qboolean soundalive;
// qboolean splitbuffer;
int numchannels;
int numchannels; // this many samples per frame
int samples; // mono samples in buffer (individual, non grouped)
// int submission_chunk; // don't mix less than this #
int samplepos; // in mono samples
int samplebits;
int speed;
unsigned char *buffer;
int speed; // this many frames per second
unsigned char *buffer; // pointer to mixed pcm buffer (not directly used by mixer)
} dma_t;
#define PITCHSHIFT 8
#define PITCHSHIFT 6 /*max audio file length = (1<<32>>PITCHSHIFT)/KHZ*/
typedef struct
{
sfx_t *sfx; // sfx number
int vol[MAXSOUNDCHANNELS]; // 0-255 volume
// int delay[MAXSOUNDCHANNELS];
int end; // end time in global paintsamples
int start; // start time in global paintsamples
int pos; // sample position in sfx, <0 means delay sound start (shifted up by 8)
int rate; // 24.8 fixed point rate scaling
int looping; // where to loop, -1 = no looping
@ -115,8 +116,7 @@ typedef struct soundcardinfo_s soundcardinfo_t;
void S_Init (void);
void S_Startup (void);
void S_Shutdown (void);
void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float pitchadj);
void S_StartSoundDelayed(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float timeofs);
void S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation, float timeofs, float pitchadj);
void S_StaticSound (sfx_t *sfx, vec3_t origin, float vol, float attenuation);
void S_StopSound (int entnum, int entchannel);
void S_StopAllSounds(qboolean clear);
@ -124,6 +124,8 @@ void S_UpdateListener(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up);
void S_GetListenerInfo(float *origin, float *forward, float *right, float *up);
void S_Update (void);
void S_ExtraUpdate (void);
void S_MixerThread(soundcardinfo_t *sc);
void S_Purge(qboolean retaintouched);
qboolean S_HaveOutput(void);
@ -132,17 +134,15 @@ void S_Music_Seek(float time);
sfx_t *S_PrecacheSound (char *sample);
void S_TouchSound (char *sample);
void S_UntouchAll(void);
void S_ClearPrecache (void);
void S_BeginPrecaching (void);
void S_EndPrecaching (void);
void S_ClearBuffer (soundcardinfo_t *sc);
void S_PaintChannels(soundcardinfo_t *sc, int endtime);
void S_InitPaintChannels (soundcardinfo_t *sc);
void S_ShutdownCard (soundcardinfo_t *sc);
void S_StopSoundCard (soundcardinfo_t *sc, int entnum, int entchannel);
void S_DefaultSpeakerConfiguration(soundcardinfo_t *sc);
void S_ResetFailedLoad(void);
@ -164,7 +164,7 @@ void S_Voip_Ignore(unsigned int plno, qboolean ignore);
#endif
qboolean S_IsPlayingSomewhere(sfx_t *s);
void ResampleSfx (sfx_t *sfx, int inrate, int inchannels, int inwidth, int insamps, int inloopstart, qbyte *data);
qboolean ResampleSfx (sfx_t *sfx, int inrate, int inchannels, int inwidth, int insamps, int inloopstart, qbyte *data);
// picks a channel based on priorities, empty slots, number of channels
channel_t *SND_PickChannel(soundcardinfo_t *sc, int entnum, int entchannel);
@ -240,9 +240,9 @@ extern cvar_t snd_usemultipledevices;
extern int snd_blocked;
void S_LocalSound (char *s);
sfxcache_t *S_LoadSound (sfx_t *s);
qboolean S_LoadSound (sfx_t *s);
typedef sfxcache_t *(*S_LoadSound_t) (sfx_t *s, qbyte *data, int datalen, int sndspeed);
typedef qboolean (*S_LoadSound_t) (sfx_t *s, qbyte *data, int datalen, int sndspeed);
qboolean S_RegisterSoundInputPlugin(S_LoadSound_t loadfnc); //called to register additional sound input plugins
wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength);
@ -279,7 +279,7 @@ 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 selfpainting; //allow the sound code to call the right functions when it feels the need (not properly supported).
int paintedtime; //used in the mixer as last-written pos (in sample pairs)
int paintedtime; //used in the mixer as last-written pos (in frames)
int oldsamplepos; //this is used to track buffer wraps
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).
@ -295,6 +295,7 @@ struct soundcardinfo_s { //windows has one defined AFTER directsound
void (*ChannelUpdate) (soundcardinfo_t *sc, channel_t *channel, unsigned int schanged);
//driver -specific
void *thread;
void *handle;
int snd_sent;
int snd_completed;

View file

@ -90,65 +90,6 @@ JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_init(JNIEnv *env, jobject o
sys_lastframe = Sys_Milliseconds();
}
}
JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_keypress(JNIEnv *env, jobject obj,
jint down, jint keycode, jint unicode)
{
Key_Event(0, keycode, unicode, down);
}
int mousecursor_x, mousecursor_y;
float mouse_x, mouse_y;
static vec2_t omouse[8];
JNIEXPORT void JNICALL Java_com_fteqw_FTEDroidEngine_motion(JNIEnv *env, jobject obj,
jint act, jint ptrid, jfloat x, jfloat y)
{
static float totalmoved[8];
static qboolean down[8];
float d[2];
if (!act && CSQC_MousePosition(x, y, ptrid))
return;
/*note that these events are not directly useful, so trigger mouse2 leaving mouse1 clean for tap events (and bypass any binds for it)*/
if (act == 1 && CSQC_KeyPress(K_MOUSE2, 0, true, ptrid))
return;
if (act == 2 && CSQC_KeyPress(K_MOUSE2, 0, false, ptrid))
return;
ptrid &= 7;
d[0] = x - omouse[ptrid][0];
d[1] = y - omouse[ptrid][1];
omouse[ptrid][0] = x;
omouse[ptrid][1] = y;
mousecursor_x = x;
mousecursor_y = y;
if (down[ptrid])
{
mouse_x += d[0];
mouse_y += d[1];
totalmoved[ptrid] += fabs(d[0]) + fabs(d[1]);
}
switch(act)
{
case 0: /*move*/
break;
case 1: /*down*/
totalmoved[ptrid] = 0;
down[ptrid] = true;
break;
case 2: /*up*/
down[ptrid] = false;
/*if it didn't move far, treat it as a regular click, if it did move a little then sorry if you just wanted a small turn!*/
if (totalmoved[ptrid] < 3)
{
Key_Event(0, K_MOUSE1, 0, 1);
Key_Event(0, K_MOUSE1, 0, 0);
}
break;
}
}
static int secbase;
double Sys_DoubleTime(void)
@ -248,6 +189,7 @@ void *Sys_GetAddressForName(dllhandle_t *module, const char *exportname)
}
void *Sys_GetGameAPI (void *parms)
{
//don't implement - fix q2 code instead
return NULL;
}
void Sys_UnloadGame(void)
@ -265,6 +207,9 @@ qboolean Sys_remove (char *path)
{
return !unlink(path);
}
void Sys_SendKeyEvents(void)
{
}
void Sys_Init(void)
{
}

View file

@ -380,7 +380,7 @@ DWORD CrashExceptionHandler (DWORD exceptionCode, LPEXCEPTION_POINTERS exception
extern qboolean vid_initializing;
qboolean oldval = vid_initializing;
vid_initializing = true;
ShowWindow(mainwindow, SW_MINIMIZE);
// ShowWindow(mainwindow, SW_MINIMIZE);
vid_initializing = oldval;
return EXCEPTION_CONTINUE_SEARCH;
}
@ -2006,7 +2006,19 @@ DWORD WINAPI threadwrapper(void *args)
tw.args = ((threadwrap_t *)args)->args;
free(args);
#ifdef CATCHCRASH
__try
{
#endif
tw.func(tw.args);
#ifdef CATCHCRASH
}
__except (CrashExceptionHandler(GetExceptionCode(), GetExceptionInformation()))
{
return 1;
}
#endif
#ifndef WIN32CRTDLL
_endthreadex(0);
@ -2065,7 +2077,7 @@ qboolean Sys_TryLockMutex(void *mutex)
qboolean Sys_LockMutex(void *mutex)
{
#ifdef _DEBUG
#if 0//def _DEBUG
/*in debug builds, trigger a debug break if we sit on a mutex for longer than 20 secs*/
if (WaitForSingleObject(mutex, 20000) == WAIT_OBJECT_0)
return true;

View file

@ -139,7 +139,7 @@ V_CalcBob
===============
*/
float V_CalcBob (int pnum)
float V_CalcBob (int pnum, qboolean queryold)
{
static double bobtime[MAX_SPLITS];
static float bob[MAX_SPLITS];
@ -148,7 +148,7 @@ float V_CalcBob (int pnum)
if (cl.spectator)
return 0;
if (!cl.onground[pnum] || cl.paused)
if (!cl.onground[pnum] || cl.paused || queryold)
return bob[pnum]; // just use old value
if (cl_bobcycle.value <= 0)
@ -790,11 +790,12 @@ float angledelta (float a)
CalcGunAngle
==================
*/
void CalcGunAngle (int pnum)
void V_CalcGunPositionAngle (int pnum, float bob)
{
float yaw, pitch, move;
static float oldyaw = 0;
static float oldpitch = 0;
int i;
yaw = r_refdef.viewangles[YAW];
pitch = -r_refdef.viewangles[PITCH];
@ -836,12 +837,36 @@ void CalcGunAngle (int pnum)
oldpitch = pitch;
cl.viewent[pnum].angles[YAW] = r_refdef.viewangles[YAW] + yaw;
cl.viewent[pnum].angles[PITCH] = - (r_refdef.viewangles[PITCH] + pitch);
cl.viewent[pnum].angles[PITCH] = r_refdef.viewangles[PITCH] + pitch;
cl.viewent[pnum].angles[YAW] = r_refdef.viewangles[YAW];
cl.viewent[pnum].angles[PITCH] = r_refdef.viewangles[PITCH];
cl.viewent[pnum].angles[ROLL] = r_refdef.viewangles[ROLL];
cl.viewent[pnum].angles[PITCH]*=-1;
AngleVectors(cl.viewent[pnum].angles, cl.viewent[pnum].axis[0], cl.viewent[pnum].axis[1], cl.viewent[pnum].axis[2]);
VectorInverse(cl.viewent[pnum].axis[1]);
cl.viewent[pnum].angles[PITCH]*=-1;
VectorCopy (r_refdef.vieworg, cl.viewent[pnum].origin);
for (i=0 ; i<3 ; i++)
{
cl.viewent[pnum].origin[i] += cl.viewent[pnum].axis[0][i]*bob*0.4;
// cl.viewent[pnum].origin[i] += cl.viewent[pnum].axis[1][i]*sin(cl.time*5.5342452354235)*0.1;
// cl.viewent[pnum].origin[i] += cl.viewent[pnum].axis[2][i]*bob*0.8;
}
// fudge position around to keep amount of weapon visible
// roughly equal with different FOV
if (scr_viewsize.value == 110)
cl.viewent[pnum].origin[2] += 1;
else if (scr_viewsize.value == 100)
cl.viewent[pnum].origin[2] += 2;
else if (scr_viewsize.value == 90)
cl.viewent[pnum].origin[2] += 1;
else if (scr_viewsize.value == 80)
cl.viewent[pnum].origin[2] += 0.5;
}
/*
@ -988,7 +1013,6 @@ void V_CalcRefdef (int pnum)
{
entity_t *view;
int i;
vec3_t forward, right, up;
float bob;
r_refdef.currentplayernum = pnum;
@ -1012,7 +1036,7 @@ void V_CalcRefdef (int pnum)
else if (v_viewheight.value)
bob=v_viewheight.value;
else
bob = V_CalcBob (pnum);
bob = V_CalcBob (pnum, false);
// refresh position from simulated origin
VectorCopy (cl.simorg[pnum], r_refdef.vieworg);
@ -1057,7 +1081,6 @@ void V_CalcRefdef (int pnum)
{
VectorCopy (cl.simangles[pnum], r_refdef.viewangles);
}
VectorCopy (r_refdef.viewangles, view->angles); //copy before it gets manipulatd
V_CalcViewRoll (pnum);
V_AddIdle (pnum);
@ -1087,28 +1110,7 @@ void V_CalcRefdef (int pnum)
}
// set up gun position
AngleVectors (view->angles, forward, right, up);
CalcGunAngle (pnum);
VectorCopy (r_refdef.vieworg, view->origin);
for (i=0 ; i<3 ; i++)
{
view->origin[i] += forward[i]*bob*0.4;
// view->origin[i] += right[i]*sin(cl.time*5.5342452354235)*0.1;
// view->origin[i] += up[i]*bob*0.8;
}
// fudge position around to keep amount of weapon visible
// roughly equal with different FOV
if (scr_viewsize.value == 110)
view->origin[2] += 1;
else if (scr_viewsize.value == 100)
view->origin[2] += 2;
else if (scr_viewsize.value == 90)
view->origin[2] += 1;
else if (scr_viewsize.value == 80)
view->origin[2] += 0.5;
V_CalcGunPositionAngle (pnum, bob);
if (cl.stats[pnum][STAT_HEALTH] > 0 && (unsigned int)cl.stats[pnum][STAT_WEAPON] >= MAX_MODELS)
view->model = NULL;

View file

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

View file

@ -151,6 +151,8 @@ typedef struct
#define Q1CONTENTS_SLIME -4
#define Q1CONTENTS_LAVA -5
#define Q1CONTENTS_SKY -6
#define Q1CONTENTS_CLIP -8
#define Q1CONTENTS_LADDER -16
// !!! if this is changed, it must be changed in asm_i386.h too !!!
typedef struct

View file

@ -2099,7 +2099,7 @@ void Mod_ParseQ3SkinFile(char *out, char *surfname, char *modelname, int skinnum
if (skinfilename)
strcpy(skinfilename, skinfilelist[skinnum]);
f = COM_LoadTempFile2(skinfilelist[skinnum]);
f = COM_LoadTempMoreFile(skinfilelist[skinnum]);
while(f)
{
@ -4714,7 +4714,7 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer)
/*attempt to load a psa file. don't die if we can't find one*/
COM_StripExtension(mod->name, basename, sizeof(basename));
buffer = COM_LoadTempFile2(va("%s.psa", basename));
buffer = COM_LoadTempMoreFile(va("%s.psa", basename));
if (buffer)
{
pos = 0;
@ -5666,10 +5666,10 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer)
galiasinfo_t *gai;
#ifndef SERVERONLY
galiasskin_t *skin;
shader_t **shaders;
#endif
galiasgroup_t *fgroup;
galiasbone_t *bones;
shader_t **shaders;
index_t *idx;
float basepose[12 * MAX_BONES];
qboolean baseposeonly;
@ -6662,7 +6662,7 @@ qboolean Mod_LoadCompositeAnim(model_t *mod, void *buffer)
if (!strcmp(com_token, "model"))
{
buffer = COM_Parse(buffer);
file = COM_LoadTempFile2(com_token);
file = COM_LoadTempMoreFile(com_token);
if (!file) //FIXME: make non fatal somehow..
{
@ -6706,7 +6706,7 @@ qboolean Mod_LoadCompositeAnim(model_t *mod, void *buffer)
grouplist = BZ_Realloc(grouplist, sizeof(galiasgroup_t)*(numgroups+1));
poseofs = BZ_Realloc(poseofs, sizeof(*poseofs)*(numgroups+1));
buffer = COM_Parse(buffer);
file = COM_LoadTempFile2(com_token);
file = COM_LoadTempMoreFile(com_token);
if (file) //FIXME: make non fatal somehow..
{
char namebkup[MAX_QPATH];
@ -6725,7 +6725,7 @@ qboolean Mod_LoadCompositeAnim(model_t *mod, void *buffer)
grouplist = BZ_Realloc(grouplist, sizeof(galiasgroup_t)*(numgroups+1));
poseofs = BZ_Realloc(poseofs, sizeof(*poseofs)*(numgroups+1));
buffer = COM_Parse(buffer);
file = COM_LoadTempFile2(com_token);
file = COM_LoadTempMoreFile(com_token);
if (file) //FIXME: make non fatal somehow..
{
char namebkup[MAX_QPATH];
@ -6746,7 +6746,7 @@ qboolean Mod_LoadCompositeAnim(model_t *mod, void *buffer)
void *np;
buffer = COM_Parse(buffer);
file = COM_LoadTempFile2(com_token);
file = COM_LoadTempMoreFile(com_token);
if (file) //FIXME: make non fatal somehow..
{
char namebkup[MAX_QPATH];

View file

@ -857,6 +857,8 @@ float MSG_FromCoord(coorddata c, int bytes)
{
case 2: //encode 1/8th precision, giving -4096 to 4096 map sizes
return LittleShort(c.b2)/8.0f;
case 3:
return LittleShort(c.b2) + (((unsigned char*)c.b)[2] * (1/255.0)); /*FIXME: RMQe uses 255, should be 256*/
case 4:
return LittleFloat(c.f);
default:

View file

@ -387,7 +387,7 @@ char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum);
int COM_filelength (FILE *f);
qbyte *COM_LoadStackFile (const char *path, void *buffer, int bufsize);
qbyte *COM_LoadTempFile (const char *path);
qbyte *COM_LoadTempFile2 (const char *path); //allocates a little bit more without freeing old temp
qbyte *COM_LoadTempMoreFile (const char *path); //allocates a little bit more without freeing old temp
qbyte *COM_LoadHunkFile (const char *path);
qbyte *COM_LoadMallocFile (const char *path);
void COM_LoadCacheFile (const char *path, struct cache_user_s *cu);

View file

@ -20,6 +20,7 @@ static unsigned int fs_restarts;
extern cvar_t com_fs_cache;
int active_fs_cachetype;
static int fs_referencetype;
int fs_finds;
struct
{
@ -511,6 +512,7 @@ int FS_FLocateFile(const char *filename, FSLF_ReturnType_e returntype, flocation
{
for (search = com_purepaths ; search ; search = search->nextpure)
{
fs_finds++;
if (search->funcs->FindFile(search->handle, loc, filename, pf))
{
if (loc)
@ -533,6 +535,7 @@ int FS_FLocateFile(const char *filename, FSLF_ReturnType_e returntype, flocation
//
for (search = com_searchpaths ; search ; search = search->next)
{
fs_finds++;
if (search->funcs->FindFile(search->handle, loc, filename, pf))
{
search->referenced |= fs_referencetype;
@ -1156,7 +1159,7 @@ qbyte *COM_LoadTempFile (const char *path)
{
return COM_LoadFile (path, 2);
}
qbyte *COM_LoadTempFile2 (const char *path)
qbyte *COM_LoadTempMoreFile (const char *path)
{
return COM_LoadFile (path, 6);
}
@ -1342,6 +1345,7 @@ static int FS_AddWildDataFiles (const char *descriptor, int size, void *vparam)
search = param->parentpath;
fs_finds++;
if (!search->funcs->FindFile(search->handle, &loc, descriptor, NULL))
return true; //not found..
vfs = search->funcs->OpenVFS(search->handle, &loc, "rb");
@ -1377,6 +1381,7 @@ static void FS_AddDataFiles(const char *purepath, const char *pathto, searchpath
for (i=0 ; ; i++)
{
snprintf (pakfile, sizeof(pakfile), "pak%i.%s", i, extension);
fs_finds++;
if (!search->funcs->FindFile(search->handle, &loc, pakfile, NULL))
break; //not found..
snprintf (pakfile, sizeof(pakfile), "%spak%i.%s", pathto, i, extension);

View file

@ -3658,6 +3658,8 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c
map_faces = NULL;
map_leaffaces = NULL;
Q1BSPX_Setup(loadmodel, mod_base, com_filesize, header.lumps, Q3LUMPS_TOTAL);
switch(qrenderer)
{
#if defined(GLQUAKE)
@ -3812,6 +3814,8 @@ cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned *c
header.lumps[i].fileofs = LittleLong (header.lumps[i].fileofs);
}
Q1BSPX_Setup(loadmodel, mod_base, com_filesize, header.lumps, Q2HEADER_LUMPS);
#ifndef SERVERONLY
if (CM_GetQ2Palette())
memcpy(d_q28to24table, host_basepal, 768);

View file

@ -132,6 +132,9 @@ typedef struct
int drop_count; // dropped packets, cleared each level
int good_count; // cleared each level
int bytesin;
int bytesout;
netadr_t remote_address;
netsrc_t sock;
int qport;

View file

@ -313,7 +313,7 @@ qboolean Netchan_CanPacket (netchan_t *chan, int rate)
return true; //don't ever drop packets due to possible routing problems when there is no routing.
if (!rate)
return true;
if (chan->cleartime < realtime + MAX_BACKUP/(float)rate)
if (chan->cleartime < realtime + 0.25)//(MAX_BACKUP/(float)rate))
return true;
return false;
}
@ -323,7 +323,7 @@ void Netchan_Block (netchan_t *chan, int bytes, int rate)
if (rate)
{
if (chan->cleartime < realtime-0.25) //0.25 allows it to be a little bursty.
chan->cleartime = realtime + bytes/(float)rate;
chan->cleartime = realtime + (bytes/(float)rate);
else
chan->cleartime += bytes/(float)rate;
}
@ -355,6 +355,7 @@ nqprot_t NQNetChan_Process(netchan_t *chan)
int sequence;
int drop;
chan->bytesin += net_message.cursize;
MSG_BeginReading (chan->netprim);
header = LongSwap(MSG_ReadLong());
@ -411,6 +412,13 @@ nqprot_t NQNetChan_Process(netchan_t *chan)
}
chan->incoming_unreliable = sequence;
// chan->frame_latency = chan->frame_latency*OLD_AVG
// + (chan->outgoing_sequence-sequence_ack)*(1.0-OLD_AVG);
chan->frame_rate = chan->frame_rate*OLD_AVG
+ (realtime-chan->last_received)*(1.0-OLD_AVG);
chan->last_received = realtime;
chan->incoming_acknowledged++;
@ -534,8 +542,8 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
else
*(int*)send_buf = BigLong(NETFLAG_DATA | send.cursize);
NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address);
chan->bytesout += send.cursize;
Netchan_Block(chan, send.cursize, rate);
sentsize += send.cursize;
if (showpackets.value)
@ -560,8 +568,6 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
*(int*)send_buf = BigLong(NETFLAG_UNRELIABLE | send.cursize);
NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address);
Netchan_Block(chan, send.cursize, rate);
sentsize += send.cursize;
if (showpackets.value)
@ -570,6 +576,8 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
, send.cursize);
send.cursize = 0;
}
chan->bytesout += sentsize;
Netchan_Block(chan, sentsize, rate);
return sentsize;
}
#endif
@ -700,6 +708,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
}
}
chan->bytesout += send.cursize;
Netchan_Block(chan, send.cursize, rate);
#ifdef SERVERONLY
if (ServerPaused())
@ -742,6 +751,8 @@ qboolean Netchan_Process (netchan_t *chan)
!NET_CompareAdr (net_from, chan->remote_address))
return false;
chan->bytesin += net_message.cursize;
// get sequence numbers
MSG_BeginReading (chan->netprim);
sequence = MSG_ReadLong ();

View file

@ -2929,6 +2929,7 @@ int NET_LocalAddressForRemote(ftenet_connections_t *collection, netadr_t *remote
void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to)
{
char buffer[64];
ftenet_connections_t *collection;
int i;
@ -2975,7 +2976,7 @@ void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to)
return;
}
Con_Printf("No route - open some ports\n");
Con_Printf("No route to %s - open some ports\n", NET_AdrToString(buffer, sizeof(buffer), to));
}
qboolean NET_EnsureRoute(ftenet_connections_t *collection, char *routename, char *host, qboolean islisten)

View file

@ -927,6 +927,8 @@ void PM_CheckWaterJump (void)
if (pmove.waterjumptime>0)
return;
if (pmove.pm_type == PM_DEAD)
return;
// don't hop out if we just jumped in
if (pmove.velocity[2] < -180)

View file

@ -616,6 +616,7 @@ enum clcq2_ops_e
#define FITZU_FRAME2 (1<<17)
#define FITZU_MODEL2 (1<<18)
#define FITZU_LERPFINISH (1<<19)
#define RMQU_SCALE (1<<20)
#endif

View file

@ -346,9 +346,351 @@ qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
}
#endif
int Q1BSP_HullPointContents(hull_t *hull, vec3_t p)
/*
the bsp tree we're walking through is the renderable hull
we need to trace a box through the world.
by its very nature, this will reach more nodes than we really want, and as we can follow a node sideways, the underlying bsp structure is no longer 100% reliable (meaning we cross planes that are entirely to one side, and follow its children too)
so all contents and solidity must come from the brushes and ONLY the brushes.
*/
struct traceinfo_s
{
switch(Q1_HullPointContents(hull, hull->firstclipnode, p))
unsigned int solidcontents;
trace_t trace;
qboolean sphere;
float radius;
/*set even for sphere traces (used for bbox tests)*/
vec3_t mins;
vec3_t maxs;
vec3_t start;
vec3_t end;
};
#include "shader.h"
void TestDrawPlane(float *normal, float dist, float r, float g, float b)
{
scenetris_t *t;
if (cl_numstris == cl_maxstris)
{
cl_maxstris+=8;
cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris);
}
t = &cl_stris[cl_numstris++];
t->shader = R_RegisterShader("testplane", "{\n{\nmap $whiteimage\nrgbgen vertex\nalphagen vertex\nblendfunc add\nnodepth\n}\n}\n");
t->firstidx = cl_numstrisidx;
t->firstvert = cl_numstrisvert;
t->numvert = 0;
t->numidx = 0;
if (cl_numstrisidx+6 > cl_maxstrisidx)
{
cl_maxstrisidx=cl_numstrisidx+6 + 64;
cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx);
}
if (cl_numstrisvert+4 > cl_maxstrisvert)
{
cl_maxstrisvert+=64;
cl_strisvertv = BZ_Realloc(cl_strisvertv, sizeof(*cl_strisvertv)*cl_maxstrisvert);
cl_strisvertt = BZ_Realloc(cl_strisvertt, sizeof(*cl_strisvertt)*cl_maxstrisvert);
cl_strisvertc = BZ_Realloc(cl_strisvertc, sizeof(*cl_strisvertc)*cl_maxstrisvert);
}
{
vec3_t tmp = {0,0.04,0.96};
vec3_t right, forward;
CrossProduct(normal, tmp, right);
VectorNormalize(right);
CrossProduct(normal, right, forward);
VectorNormalize(forward);
VectorScale( normal, dist, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], 8192, right, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], 8192, forward, cl_strisvertv[cl_numstrisvert]);
Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2);
cl_numstrisvert++;
VectorScale( normal, dist, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], 8192, right, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], -8192, forward, cl_strisvertv[cl_numstrisvert]);
Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2);
cl_numstrisvert++;
VectorScale( normal, dist, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], -8192, right, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], -8192, forward, cl_strisvertv[cl_numstrisvert]);
Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2);
cl_numstrisvert++;
VectorScale( normal, dist, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], -8192, right, cl_strisvertv[cl_numstrisvert]);
VectorMA(cl_strisvertv[cl_numstrisvert], 8192, forward, cl_strisvertv[cl_numstrisvert]);
Vector4Set(cl_strisvertc[cl_numstrisvert], r, g, b, 0.2);
cl_numstrisvert++;
}
/*build the triangles*/
cl_strisidx[cl_numstrisidx++] = t->numvert + 0;
cl_strisidx[cl_numstrisidx++] = t->numvert + 1;
cl_strisidx[cl_numstrisidx++] = t->numvert + 2;
cl_strisidx[cl_numstrisidx++] = t->numvert + 0;
cl_strisidx[cl_numstrisidx++] = t->numvert + 2;
cl_strisidx[cl_numstrisidx++] = t->numvert + 3;
t->numidx = cl_numstrisidx - t->firstidx;
t->numvert += 4;
}
static void Q1BSP_ClipToBrushes(struct traceinfo_s *traceinfo, mbrush_t *brush)
{
struct mbrushplane_s *plane;
struct mbrushplane_s *enterplane;
int i, j;
vec3_t ofs;
qboolean startout, endout;
float d1,d2,dist,enterdist=0;
float f, enterfrac, exitfrac;
for (; brush; brush = brush->next)
{
/*ignore if its not solid to us*/
if (!(traceinfo->solidcontents & brush->contents))
continue;
startout = false;
endout = false;
enterplane= NULL;
enterfrac = -1;
exitfrac = 10;
for (i = brush->numplanes, plane = brush->planes; i; i--, plane++)
{
/*calculate the distance based upon the shape of the object we're tracing for*/
if (traceinfo->sphere)
{
dist = plane->dist + traceinfo->radius;
}
else
{
for (j=0 ; j<3 ; j++)
{
if (plane->normal[j] < 0)
ofs[j] = traceinfo->maxs[j];
else
ofs[j] = traceinfo->mins[j];
}
dist = DotProduct (ofs, plane->normal);
dist = plane->dist - dist;
}
d1 = DotProduct (traceinfo->start, plane->normal) - dist;
d2 = DotProduct (traceinfo->end, plane->normal) - dist;
if (d1 >= 0)
startout = true;
if (d2 > 0)
endout = true;
//if we're fully outside any plane, then we cannot possibly enter the brush, skip to the next one
if (d1 > 0 && d2 >= 0)
goto nextbrush;
//if we're fully inside the plane, then whatever is happening is not relevent for this plane
if (d1 < 0 && d2 <= 0)
continue;
f = d1 / (d1-d2);
if (d1 > d2)
{
//entered the brush. favour the furthest fraction to avoid extended edges (yay for convex shapes)
if (enterfrac < f)
{
enterfrac = f;
enterplane = plane;
enterdist = dist;
}
}
else
{
//left the brush, favour the nearest plane (smallest frac)
if (exitfrac > f)
{
exitfrac = f;
}
}
}
if (!startout)
{
traceinfo->trace.startsolid = true;
if (!endout)
traceinfo->trace.allsolid = true;
traceinfo->trace.contents |= brush->contents;
return;
}
if (enterfrac != -1 && enterfrac < exitfrac)
{
//impact!
if (enterfrac < traceinfo->trace.fraction)
{
traceinfo->trace.fraction = enterfrac;
traceinfo->trace.plane.dist = enterdist;
VectorCopy(enterplane->normal, traceinfo->trace.plane.normal);
traceinfo->trace.contents = brush->contents;
}
}
nextbrush:
;
}
}
static void Q1BSP_InsertBrush(mnode_t *node, mbrush_t *brush, vec3_t bmins, vec3_t bmaxs)
{
vec3_t near, far;
float nd, fd;
int i;
while(1)
{
if (node->contents < 0) /*leaf, so no smaller node to put it in (I'd be surprised if it got this far)*/
{
brush->next = node->brushes;
node->brushes = brush;
return;
}
for (i = 0; i < 3; i++)
{
if (node->plane->normal[i] > 0)
{
near[i] = bmins[i];
far[i] = bmaxs[i];
}
else
{
near[i] = bmaxs[i];
far[i] = bmins[i];
}
}
nd = DotProduct(node->plane->normal, near) - node->plane->dist;
fd = DotProduct(node->plane->normal, far) - node->plane->dist;
/*if its fully on either side, continue walking*/
if (nd < 0 && fd < 0)
node = node->children[1];
else if (nd > 0 && fd > 0)
node = node->children[0];
else
{
/*plane crosses bbox, so insert here*/
brush->next = node->brushes;
node->brushes = brush;
return;
}
}
}
static void Q1BSP_RecursiveBrushCheck (struct traceinfo_s *traceinfo, mnode_t *node, float p1f, float p2f, vec3_t p1, vec3_t p2)
{
mplane_t *plane;
float t1, t2;
float frac;
int i;
vec3_t mid;
int side;
float midf;
float offset;
if (node->brushes)
{
Q1BSP_ClipToBrushes(traceinfo, node->brushes);
}
if (traceinfo->trace.fraction < p1f)
{
//already hit something closer than this node
return;
}
if (node->contents < 0)
{
//we're in a leaf
return;
}
//
// find the point distances
//
plane = node->plane;
if (plane->type < 3)
{
t1 = p1[plane->type] - plane->dist;
t2 = p2[plane->type] - plane->dist;
if (plane->normal[plane->type] < 0)
offset = -traceinfo->mins[plane->type];
else
offset = traceinfo->maxs[plane->type];
}
else
{
t1 = DotProduct (plane->normal, p1) - plane->dist;
t2 = DotProduct (plane->normal, p2) - plane->dist;
offset = 0;
for (i = 0; i < 3; i++)
{
if (plane->normal[i] < 0)
offset += plane->normal[i] * -traceinfo->mins[i];
else
offset += plane->normal[i] * traceinfo->maxs[i];
}
}
/*if we're fully on one side of the trace, go only down that side*/
if (t1 >= offset && t2 >= offset)
{
Q1BSP_RecursiveBrushCheck (traceinfo, node->children[0], p1f, p2f, p1, p2);
return;
}
if (t1 < -offset && t2 < -offset)
{
Q1BSP_RecursiveBrushCheck (traceinfo, node->children[1], p1f, p2f, p1, p2);
return;
}
// put the crosspoint DIST_EPSILON pixels on the near side
if (t1 < 0)
{
frac = (t1 + DIST_EPSILON)/(t1-t2);
side = 1;
}
else
{
frac = (t1 - DIST_EPSILON)/(t1-t2);
side = 0;
}
if (frac < 0)
frac = 0;
if (frac > 1)
frac = 1;
midf = p1f + (p2f - p1f)*frac;
for (i=0 ; i<3 ; i++)
mid[i] = p1[i] + frac*(p2[i] - p1[i]);
// move up to the node
Q1BSP_RecursiveBrushCheck (traceinfo, node->children[side], p1f, midf, p1, mid);
// go past the node
Q1BSP_RecursiveBrushCheck (traceinfo, node->children[side^1], midf, p2f, mid, p2);
}
static unsigned int Q1BSP_TranslateContents(int contents)
{
switch(contents)
{
case Q1CONTENTS_EMPTY:
return FTECONTENTS_EMPTY;
@ -362,12 +704,19 @@ int Q1BSP_HullPointContents(hull_t *hull, vec3_t p)
return FTECONTENTS_LAVA;
case Q1CONTENTS_SKY:
return FTECONTENTS_SKY;
case Q1CONTENTS_LADDER:
return FTECONTENTS_LADDER;
default:
Sys_Error("Q1_PointContents: Unknown contents type");
Sys_Error("Q1BSP_TranslateContents: Unknown contents type - %i", contents);
return FTECONTENTS_SOLID;
}
}
int Q1BSP_HullPointContents(hull_t *hull, vec3_t p)
{
return Q1BSP_TranslateContents(Q1_HullPointContents(hull, hull->firstclipnode, p));
}
unsigned int Q1BSP_PointContents(model_t *model, vec3_t axis[3], vec3_t point)
{
if (axis)
@ -381,6 +730,121 @@ unsigned int Q1BSP_PointContents(model_t *model, vec3_t axis[3], vec3_t point)
return Q1BSP_HullPointContents(&model->hulls[0], point);
}
void Q1BSP_LoadBrushes(model_t *model)
{
struct {
unsigned int ver;
unsigned int modelnum;
unsigned int numbrushes;
unsigned int numplanes;
} *permodel;
struct {
float mins[3];
float maxs[3];
signed short contents;
unsigned short numplanes;
} *perbrush;
/*
Note to implementors:
a pointy brush with angles pointier than 90 degrees will extend further than any adjacent brush, thus creating invisible walls with larger expansions.
the engine inserts 6 axial planes acording to the bbox, thus the qbsp need not write any axial planes
note that doing it this way probably isn't good if you want to query textures...
*/
struct {
vec3_t normal;
float dist;
} *perplane;
static vec3_t axis[3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
int br, pl, remainingplanes;
mbrush_t *brush;
mnode_t *rootnode;
unsigned int lumpsizeremaining;
model->engineflags &= ~MDLF_HASBRUSHES;
permodel = Q1BSPX_FindLump("BRUSHLIST", &lumpsizeremaining);
if (!permodel)
return;
while (lumpsizeremaining)
{
if (lumpsizeremaining < sizeof(*permodel))
return;
permodel->ver = LittleLong(permodel->ver);
permodel->modelnum = LittleLong(permodel->modelnum);
permodel->numbrushes = LittleLong(permodel->numbrushes);
permodel->numplanes = LittleLong(permodel->numplanes);
if (permodel->ver != 1 || lumpsizeremaining < sizeof(*permodel) + permodel->numbrushes*sizeof(*perbrush) + permodel->numplanes*sizeof(*perplane))
return;
//find the correct rootnode for the model
rootnode = model->nodes;
if (permodel->modelnum > model->numsubmodels)
return;
if (permodel->modelnum)
rootnode += model->submodels[permodel->modelnum-1].headnode[0];
brush = Hunk_Alloc((sizeof(*brush) - sizeof(brush->planes[0]))*permodel->numbrushes + sizeof(brush->planes[0])*(permodel->numbrushes*6+permodel->numplanes));
remainingplanes = permodel->numplanes;
perbrush = (void*)(permodel+1);
for (br = 0; br < permodel->numbrushes; br++)
{
/*byteswap it all in place*/
perbrush->mins[0] = LittleFloat(perbrush->mins[0]);
perbrush->mins[1] = LittleFloat(perbrush->mins[1]);
perbrush->mins[2] = LittleFloat(perbrush->mins[2]);
perbrush->maxs[0] = LittleFloat(perbrush->maxs[0]);
perbrush->maxs[1] = LittleFloat(perbrush->maxs[1]);
perbrush->maxs[2] = LittleFloat(perbrush->maxs[2]);
perbrush->contents = LittleShort(perbrush->contents);
perbrush->numplanes = LittleShort(perbrush->numplanes);
/*make sure planes don't overflow*/
if (perbrush->numplanes > remainingplanes)
return;
remainingplanes-=perbrush->numplanes;
/*set up the mbrush from the file*/
brush->contents = Q1BSP_TranslateContents(perbrush->contents);
brush->numplanes = perbrush->numplanes;
for (pl = 0, perplane = (void*)(perbrush+1); pl < perbrush->numplanes; pl++, perplane++)
{
brush->planes[pl].normal[0] = LittleFloat(perplane->normal[0]);
brush->planes[pl].normal[1] = LittleFloat(perplane->normal[1]);
brush->planes[pl].normal[2] = LittleFloat(perplane->normal[2]);
brush->planes[pl].dist = LittleFloat(perplane->dist);
}
/*and add axial planes acording to the brush's bbox*/
for (pl = 0; pl < 3; pl++)
{
VectorCopy(axis[pl], brush->planes[brush->numplanes].normal);
brush->planes[brush->numplanes].dist = perbrush->maxs[pl];
brush->numplanes++;
}
for (pl = 0; pl < 3; pl++)
{
VectorNegate(axis[pl], brush->planes[brush->numplanes].normal);
brush->planes[brush->numplanes].dist = -perbrush->mins[pl];
brush->numplanes++;
}
/*link it in to the bsp tree*/
Q1BSP_InsertBrush(rootnode, brush, perbrush->mins, perbrush->maxs);
/*set up for the next brush*/
brush = (void*)&brush->planes[brush->numplanes];
perbrush = (void*)perplane;
}
/*move on to the next model*/
lumpsizeremaining -= sizeof(*permodel) + permodel->numbrushes*sizeof(*perbrush) + permodel->numplanes*sizeof(*perplane);
permodel = (void*)((char*)permodel + sizeof(*permodel) + permodel->numbrushes*sizeof(*perbrush) + permodel->numplanes*sizeof(*perplane));
}
/*parsing was successful! flag it as okay*/
model->engineflags |= MDLF_HASBRUSHES;
}
qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int hitcontentsmask, trace_t *trace)
{
hull_t *hull;
@ -388,11 +852,47 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3]
vec3_t start_l, end_l;
vec3_t offset;
VectorSubtract (maxs, mins, size);
if ((model->engineflags & MDLF_HASBRUSHES))// && (size[0] || size[1] || size[2]))
{
struct traceinfo_s traceinfo;
memset (&traceinfo.trace, 0, sizeof(trace_t));
traceinfo.trace.fraction = 1;
traceinfo.trace.allsolid = false;
VectorCopy(mins, traceinfo.mins);
VectorCopy(maxs, traceinfo.maxs);
VectorCopy(start, traceinfo.start);
VectorCopy(end, traceinfo.end);
traceinfo.sphere = false;
/* traceinfo.sphere = true;
traceinfo.radius = 48;
traceinfo.mins[0] = -traceinfo.radius;
traceinfo.mins[1] = -traceinfo.radius;
traceinfo.mins[2] = -traceinfo.radius;
traceinfo.maxs[0] = traceinfo.radius;
traceinfo.maxs[1] = traceinfo.radius;
traceinfo.maxs[2] = traceinfo.radius;
*/
traceinfo.solidcontents = hitcontentsmask;
Q1BSP_RecursiveBrushCheck(&traceinfo, model->nodes, 0, 1, start, end);
memcpy(trace, &traceinfo.trace, sizeof(trace_t));
if (trace->fraction < 1)
{
float d1 = DotProduct(start, trace->plane.normal) - trace->plane.dist;
float d2 = DotProduct(end, trace->plane.normal) - trace->plane.dist;
float f = (d1 - DIST_EPSILON) / (d1 - d2);
if (f < 0)
f = 0;
trace->fraction = f;
}
VectorInterpolate(start, trace->fraction, end, trace->endpos);
return trace->fraction != 1;
}
memset (trace, 0, sizeof(trace_t));
trace->fraction = 1;
trace->allsolid = true;
VectorSubtract (maxs, mins, size);
if (forcehullnum >= 1 && forcehullnum <= MAX_MAP_HULLSM && model->hulls[forcehullnum-1].available)
hull = &model->hulls[forcehullnum-1];
else
@ -1375,11 +1875,79 @@ PVS type stuff
Init stuff
*/
void Q1BSP_Init(void)
{
memset (mod_novis, 0xff, sizeof(mod_novis));
}
typedef struct {
char lumpname[24]; // up to 23 chars, zero-padded
int fileofs; // from file start
int filelen;
} bspx_lump_t;
typedef struct {
char id[4]; // 'BSPX'
int numlumps;
bspx_lump_t lumps[1];
} bspx_header_t;
static char *bspxbase;
static bspx_header_t *bspxheader;
//supported lumps:
//RGBLIGHTING (.lit)
//LIGHTINGDIR (.lux)
void *Q1BSPX_FindLump(char *lumpname, int *lumpsize)
{
int i;
if (!bspxheader)
return NULL;
for (i = 0; i < bspxheader->numlumps; i++)
{
if (!strncmp(bspxheader->lumps[i].lumpname, lumpname, 24))
{
*lumpsize = bspxheader->lumps[i].filelen;
return bspxbase + bspxheader->lumps[i].fileofs;
}
}
return NULL;
}
void Q1BSPX_Setup(model_t *mod, char *filebase, unsigned int filelen, lump_t *lumps, int numlumps)
{
int i;
int offs = 0;
bspx_header_t *h;
bspxbase = filebase;
bspxheader = NULL;
for (i = 0; i < numlumps; i++, lumps++)
{
if (offs < lumps->fileofs + lumps->filelen)
offs = lumps->fileofs + lumps->filelen;
}
offs = (offs + 3) & ~3;
if (offs + sizeof(*bspxheader) > filelen)
return; /*no space for it*/
h = (bspx_header_t*)(filebase + offs);
i = LittleLong(h->numlumps);
/*verify the header*/
if (*(int*)h->id != *(int*)"BSPX" ||
i < 0 ||
offs + sizeof(*h) + sizeof(h->lumps[0])*(i-1) > filelen)
return;
h->numlumps = i;
while(i-->0)
{
h->lumps[i].fileofs = LittleLong(h->lumps[i].fileofs);
h->lumps[i].filelen = LittleLong(h->lumps[i].filelen);
if (h->lumps[i].fileofs + h->lumps[i].filelen > filelen)
return;
}
bspxheader = h;
}
//sets up the functions a server needs.
//fills in bspfuncs_t

View file

@ -1677,6 +1677,7 @@ void *Cache_Check(cache_user_t *c)
void Cache_Flush(void)
{
S_Purge(false);
while(cache_head)
{
Cache_Free(cache_head->user);

View file

@ -102,91 +102,74 @@ public class FTEDroidActivity extends Activity
{
private final FTERenderer rndr;
private byte[] audbuf;
private AudioTrack at;
private void audioInit()
private audiothreadclass audiothread;
private class audiothreadclass extends Thread
{
final int notifframes = 2048;
if (at != null)
at.stop();
boolean timetodie;
@Override
public void run()
{
byte[] audbuf = new byte[2048];
int avail;
int sspeed = 11025;
int speakers = 1;
int sz = 4*AudioTrack.getMinBufferSize(sspeed, ((speakers==2)?AudioFormat.CHANNEL_CONFIGURATION_STEREO:AudioFormat.CHANNEL_CONFIGURATION_MONO), AudioFormat.ENCODING_PCM_16BIT);
if (sz < notifframes*2)
sz = notifframes*2;
at = new AudioTrack(AudioManager.STREAM_MUSIC, sspeed, ((speakers==2)?AudioFormat.CHANNEL_CONFIGURATION_STEREO:AudioFormat.CHANNEL_CONFIGURATION_MONO), AudioFormat.ENCODING_PCM_16BIT, sz, AudioTrack.MODE_STREAM);
final int framesz = 2; /*mono 16bit*/
audbuf = new byte[notifframes*framesz];
at.setPlaybackPositionUpdateListener(new AudioTrack.OnPlaybackPositionUpdateListener()
{
@Override
public void onMarkerReached(AudioTrack track)
{
}
@Override
public void onPeriodicNotification(AudioTrack track)
{
int avail = FTEDroidEngine.paintaudio(audbuf, audbuf.length);
at.write(audbuf, 0, notifframes*framesz);
}
});
at.setPositionNotificationPeriod(notifframes);
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, sspeed, ((speakers==2)?AudioFormat.CHANNEL_CONFIGURATION_STEREO:AudioFormat.CHANNEL_CONFIGURATION_MONO), AudioFormat.ENCODING_PCM_16BIT, sz, AudioTrack.MODE_STREAM);
at.setStereoVolume(1, 1);
at.play();
/*buffer needs to be completely full before it'll start playing*/
while(sz > 0)
while(!timetodie)
{
at.write(audbuf, 0, notifframes*framesz);
sz -= notifframes;
}
}
public void resume()
{
/*poke audio into submission*/
if (at != null)
at.play();
avail = FTEDroidEngine.paintaudio(audbuf, audbuf.length);
at.write(audbuf, 0, avail);
}
public FTEView(FTEDroidActivity context)
at.stop();
}
public void killoff()
{
super(context);
timetodie = true;
try
{
join();
}
catch(InterruptedException e)
{
}
}
};
rndr = new FTERenderer(context, context);
// setEGLConfigChooser(new FTEEGLConfig());
setRenderer(rndr);
setFocusable(true);
setFocusableInTouchMode(true);
android.util.Log.i("FTEDroid", "starting audio");
private void audioInit()
{
if (audiothread == null)
{
audiothread = new audiothreadclass();
audiothread.start();
}
}
public void audioStop()
{
if (audiothread != null)
{
audiothread.killoff();
audiothread = null;
}
}
public void audioResume()
{
audioStop();
audioInit();
android.util.Log.i("FTEDroid", "audio running");
}
private void sendKey(final boolean presseddown, final int qcode, final int unicode)
{
queueEvent(new Runnable()
{
public void run()
{
FTEDroidEngine.keypress(presseddown?1:0, qcode, unicode);
}
});
}
@Override
public boolean onTouchEvent(final MotionEvent event)
{
/*the test itself requires android 4...*/
if (android.os.Build.VERSION.SDK_INT >= 5)
private FTELegacyInputEvent inputevent;
class FTEMultiTouchInputEvent extends FTELegacyInputEvent
{
/*Requires API level 5+ (android 2.0+)*/
queueEvent(new Runnable()
{
private void domove()
private void domove(MotionEvent event)
{
final int pointerCount = event.getPointerCount();
int i;
@ -194,13 +177,13 @@ public class FTEDroidActivity extends Activity
FTEDroidEngine.motion(0, event.getPointerId(i), event.getX(i), event.getY(i));
}
public void run()
public boolean go(MotionEvent event)
{
int id;
float x, y;
final int act = event.getAction();
domove();
domove(event);
switch(act & event.ACTION_MASK)
{
@ -222,15 +205,15 @@ public class FTEDroidActivity extends Activity
break;
case MotionEvent.ACTION_MOVE:
break;
default:
return false;
}
return true;
}
}
});
}
else
class FTELegacyInputEvent
{
queueEvent(new Runnable()
{
public void run()
public boolean go(MotionEvent event)
{
final int act = event.getAction();
final float x = event.getX();
@ -248,12 +231,42 @@ public class FTEDroidActivity extends Activity
break;
case MotionEvent.ACTION_MOVE:
break;
}
}
});
default:
return false;
}
return true;
}
}
public FTEView(FTEDroidActivity context)
{
super(context);
if (android.os.Build.VERSION.SDK_INT >= 5)
inputevent = new FTEMultiTouchInputEvent();
else
inputevent = new FTELegacyInputEvent();
rndr = new FTERenderer(context, context);
// setEGLConfigChooser(new FTEEGLConfig());
setRenderer(rndr);
setFocusable(true);
setFocusableInTouchMode(true);
android.util.Log.i("FTEDroid", "starting audio");
audioInit();
android.util.Log.i("FTEDroid", "audio running");
}
private void sendKey(final boolean presseddown, final int qcode, final int unicode)
{
FTEDroidEngine.keypress(presseddown?1:0, qcode, unicode);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
return inputevent.go(event);
}
/*
@Override
public boolean onTrackballEvent(MotionEvent event)
@ -323,6 +336,12 @@ public class FTEDroidActivity extends Activity
}
}
private boolean runningintheemulator()
{
android.util.Log.i("FTEDroid", "model: " + android.os.Build.MODEL + " product: " + android.os.Build.PRODUCT + " device: " + android.os.Build.DEVICE);
return android.os.Build.MODEL.equals("sdk") && android.os.Build.PRODUCT.equals("sdk") && android.os.Build.DEVICE.equals("generic");
}
@Override
public void onCreate(Bundle savedInstanceState)
{
@ -339,11 +358,21 @@ public class FTEDroidActivity extends Activity
// setContentView(R.layout.main);
if (runningintheemulator())
{
android.util.Log.i("FTEDroid", "emulator detected - skipping sensors to avoid emulator hangs");
sensorman = null;
}
else
{
android.util.Log.i("FTEDroid", "init sensor manager");
sensorman = (SensorManager)getSystemService(SENSOR_SERVICE);
android.util.Log.i("FTEDroid", "init accelerometer");
}
if (sensorman != null)
{
android.util.Log.i("FTEDroid", "init accelerometer");
sensoracc = sensorman.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
android.util.Log.i("FTEDroid", "done");
}
@ -354,7 +383,7 @@ public class FTEDroidActivity extends Activity
if (sensorman != null && sensoracc != null)
sensorman.registerListener((SensorEventListener)view, sensoracc, SensorManager.SENSOR_DELAY_GAME);
view.resume();
view.audioResume();
}
@Override
@ -362,6 +391,7 @@ public class FTEDroidActivity extends Activity
{
if (sensorman != null && sensoracc != null)
sensorman.unregisterListener(view);
view.audioStop();
super.onStop();
}
@ -370,6 +400,7 @@ public class FTEDroidActivity extends Activity
{
if (sensorman != null && sensoracc != null)
sensorman.unregisterListener(view);
view.audioStop();
super.onPause();
}
}

View file

@ -2685,12 +2685,7 @@ void GLBE_SelectMode(backendmode_t mode)
case BEM_STENCIL:
GL_DeSelectProgram();
if (shaderstate.curpolyoffset.factor || shaderstate.curpolyoffset.unit)
{
shaderstate.curpolyoffset.factor = 0;
shaderstate.curpolyoffset.unit = 0;
qglDisable(GL_POLYGON_OFFSET_FILL);
}
BE_PushOffsetShadow(false);
/*BEM_STENCIL doesn't support mesh writing*/
qglDisableClientState(GL_COLOR_ARRAY);

View file

@ -245,6 +245,7 @@ void RMod_Think (void)
#endif
if (relitsurface >= lightmodel->numsurfaces)
{
vfsfile_t *f;
char filename[MAX_QPATH];
Con_Printf("Finished lighting %s\n", lightmodel->name);
@ -266,14 +267,30 @@ void RMod_Think (void)
{
COM_StripExtension(lightmodel->name, filename, sizeof(filename));
COM_DefaultExtension(filename, ".lux", sizeof(filename));
FS_WriteFile(filename, lightmodel->deluxdata-8, numlightdata*3+8, FS_GAME);
f = FS_OpenVFS(filename, "wb", FS_GAMEONLY);
if (f)
{
VFS_WRITE(f, "QLIT\1\0\0\0", 8);
VFS_WRITE(f, lightmodel->deluxdata, numlightdata*3);
VFS_CLOSE(f);
}
else
Con_Printf("Unable to write \"%s\"\n", filename);
}
if (writelitfile) //the user might already have a lit file (don't overwrite it).
{
COM_StripExtension(lightmodel->name, filename, sizeof(filename));
COM_DefaultExtension(filename, ".lit", sizeof(filename));
FS_WriteFile(filename, lightmodel->lightdata-8, numlightdata*3+8, FS_GAME);
f = FS_OpenVFS(filename, "wb", FS_GAMEONLY);
if (f)
{
VFS_WRITE(f, "QLIT\1\0\0\0", 8);
VFS_WRITE(f, lightmodel->lightdata, numlightdata*3);
VFS_CLOSE(f);
}
else
Con_Printf("Unable to write \"%s\"\n", filename);
}
}
}
@ -1059,6 +1076,8 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n"));
if (!l->filelen)
{
Con_Printf(CON_WARNING "warning: %s contains no texture data\n", loadmodel->name);
loadmodel->numtextures = 1;
loadmodel->textures = Hunk_AllocName (1 * sizeof(*loadmodel->textures), loadname);
@ -1376,8 +1395,8 @@ void RMod_NowLoadExternal(void)
if (!TEXVALID(tn.base))
{
tn.base = R_LoadHiResTexture(tx->name, "bmodels", IF_NOALPHA|IF_MIPCAP);
if (!TEXVALID(tn.base))
tn.base = R_LoadReplacementTexture("light1_4", NULL, IF_NOALPHA|IF_MIPCAP); //a fallback. :/
// if (!TEXVALID(tn.base))
// tn.base = R_LoadReplacementTexture("light1_4", NULL, IF_NOALPHA|IF_MIPCAP); //a fallback. :/
}
}
if (!TEXVALID(tn.bump) && *tx->name != '{' && r_loadbumpmapping)
@ -1447,8 +1466,14 @@ Mod_LoadLighting
*/
void RMod_LoadLighting (lump_t *l)
{
qboolean luxtmp = true;
qboolean littmp = true;
qbyte *luxdata = NULL;
int mapcomeswith24bitcolouredlighting = false;
qbyte *litdata = NULL;
qbyte *lumdata = NULL;
qbyte *out;
unsigned int samples;
extern cvar_t gl_overbright;
loadmodel->engineflags &= ~MDLF_RGBLIGHTING;
@ -1468,15 +1493,20 @@ void RMod_LoadLighting (lump_t *l)
loadmodel->lightdata = NULL;
loadmodel->deluxdata = NULL;
if (!l->filelen)
{
return;
}
if (loadmodel->fromgame == fg_halflife || loadmodel->fromgame == fg_quake2 || loadmodel->fromgame == fg_quake3)
mapcomeswith24bitcolouredlighting = true;
{
litdata = mod_base + l->fileofs;
samples = l->filelen/3;
}
else
{
lumdata = mod_base + l->fileofs;
samples = l->filelen;
}
if (!samples)
return;
if (!mapcomeswith24bitcolouredlighting && r_loadlits.ival && r_deluxemapping.ival) //fixme: adjust the light intensities.
if (!luxdata && r_loadlits.ival && r_deluxemapping.ival)
{ //the map util has a '-scalecos X' parameter. use 0 if you're going to use only just lux. without lux scalecos 0 is hideous.
char luxname[MAX_QPATH];
if (!luxdata)
@ -1485,6 +1515,7 @@ void RMod_LoadLighting (lump_t *l)
COM_StripExtension(loadmodel->name, luxname, sizeof(luxname));
COM_DefaultExtension(luxname, ".lux", sizeof(luxname));
luxdata = COM_LoadHunkFile(luxname);
luxtmp = false;
}
if (!luxdata)
{
@ -1493,15 +1524,24 @@ void RMod_LoadLighting (lump_t *l)
strcat(luxname, ".lux");
luxdata = COM_LoadHunkFile(luxname);
luxtmp = false;
}
if (!luxdata)
if (!luxdata) //dp...
{
COM_StripExtension(COM_SkipPath(loadmodel->name), luxname+5, sizeof(luxname)-5);
COM_DefaultExtension(luxname, ".dlit", sizeof(luxname));
luxdata = COM_LoadHunkFile(luxname);
luxtmp = false;
}
if (luxdata)
if (!luxdata)
{
int size;
luxdata = Q1BSPX_FindLump("LIGHTINGDIR", &size);
if (size != samples*3)
luxdata = NULL;
luxtmp = true;
}
else if (luxdata)
{
if (l->filelen && l->filelen != (com_filesize-8)/3)
{
@ -1529,9 +1569,8 @@ void RMod_LoadLighting (lump_t *l)
}
}
if (!mapcomeswith24bitcolouredlighting && r_loadlits.value)
if (!litdata && r_loadlits.value)
{
qbyte *litdata = NULL;
char *litname;
char litnamemaps[MAX_QPATH];
char litnamelits[MAX_QPATH];
@ -1559,51 +1598,55 @@ void RMod_LoadLighting (lump_t *l)
}
litdata = COM_LoadHunkFile(litname);
COM_StripExtension(COM_SkipPath(loadmodel->name), litname+5, sizeof(litname)-5);
strcat(litname, ".lit");
if (litdata && (litdata[0] == 'Q' && litdata[1] == 'L' && litdata[2] == 'I' && litdata[3] == 'T'))
littmp = false;
if (!litdata)
{
if (LittleLong(*(int *)&litdata[4]) == 1 && l->filelen && l->filelen != (com_filesize-8)/3)
int size;
litdata = Q1BSPX_FindLump("RGBLIGHTING", &size);
if (size != samples*3)
litdata = NULL;
littmp = true;
}
else if (litdata[0] == 'Q' && litdata[1] == 'L' && litdata[2] == 'I' && litdata[3] == 'T')
{
if (LittleLong(*(int *)&litdata[4]) == 1 && l->filelen && samples*3 != (com_filesize-8))
Con_Printf("lit \"%s\" doesn't match level. Ignored.\n", litname);
else if (LittleLong(*(int *)&litdata[4]) != 1)
Con_Printf("lit \"%s\" isn't version 1.\n", litname);
else
else if (lumdata)
{
float prop;
int i;
qbyte *normal;
//load it
loadmodel->lightdata = litdata+8;
loadmodel->engineflags |= MDLF_RGBLIGHTING;
qbyte *lum;
qbyte *lit;
litdata += 8;
//now some cheat protection.
lum = lumdata;
lit = litdata;
normal = mod_base + l->fileofs;
litdata = loadmodel->lightdata;
for (i = 0; i < l->filelen; i++) //force it to the same intensity. (or less, depending on how you see it...)
for (i = 0; i < samples; i++) //force it to the same intensity. (or less, depending on how you see it...)
{
#define m(a, b, c) (a>(b>c?b:c)?a:(b>c?b:c))
prop = (float)m(litdata[0], litdata[1], litdata[2]);
prop = (float)m(lit[0], lit[1], lit[2]);
if (!prop)
{
litdata[0] = lmgamma[*normal];
litdata[1] = lmgamma[*normal];
litdata[2] = lmgamma[*normal];
lit[0] = *lum;
lit[1] = *lum;
lit[2] = *lum;
}
else
{
prop = lmgamma[*normal] / prop;
litdata[0] *= prop;
litdata[1] *= prop;
litdata[2] *= prop;
prop = *lum / prop;
lit[0] *= prop;
lit[1] *= prop;
lit[2] *= prop;
}
normal++;
litdata+=3;
lum++;
lit+=3;
}
//end anti-cheat
}
@ -1613,85 +1656,87 @@ void RMod_LoadLighting (lump_t *l)
// else
//failed to find
}
if (mapcomeswith24bitcolouredlighting)
loadmodel->engineflags |= MDLF_RGBLIGHTING;
#ifdef RUNTIMELIGHTING
else if (r_loadlits.value == 2 && !lightmodel && (!(loadmodel->engineflags & MDLF_RGBLIGHTING) || (!luxdata && r_deluxemapping.ival)))
if (r_loadlits.value == 2 && !lightmodel && (!litdata || (!luxdata && r_deluxemapping.ival)))
{
qbyte *litdata = NULL;
int i;
qbyte *normal;
writelitfile = !(loadmodel->engineflags & MDLF_RGBLIGHTING);
loadmodel->engineflags |= MDLF_RGBLIGHTING;
loadmodel->lightdata = Hunk_AllocName ( l->filelen*3+8, loadname);
strcpy(loadmodel->lightdata, "QLIT");
((int*)loadmodel->lightdata)[1] = LittleLong(1);
loadmodel->lightdata += 8;
litdata = loadmodel->lightdata;
normal = mod_base + l->fileofs;
for (i = 0; i < l->filelen; i++)
{
*litdata++ = lmgamma[*normal];
*litdata++ = lmgamma[*normal];
*litdata++ = lmgamma[*normal];
normal++;
}
if (r_deluxemapping.ival)
{
loadmodel->deluxdata = Hunk_AllocName ( l->filelen*3+8, loadname);
strcpy(loadmodel->deluxdata, "QLIT");
((int*)loadmodel->deluxdata)[1] = LittleLong(1);
loadmodel->deluxdata += 8;
litdata = loadmodel->deluxdata;
{
for (i = 0; i < l->filelen; i++)
{
*litdata++ = 0.5f*255;
*litdata++ = 0.5f*255;
*litdata++ = 255;
}
}
}
numlightdata = l->filelen;
lightmodel = loadmodel;
relitsurface = 0;
return;
}
/*if we're relighting, make sure there's the proper lit data to be updated*/
if (lightmodel == loadmodel && !litdata)
{
int i;
litdata = Hunk_AllocName(samples*3, "lit data");
littmp = false;
if (lumdata)
{
for (i = 0; i < samples; i++)
{
litdata[i*3+0] = lumdata[i];
litdata[i*3+1] = lumdata[i];
litdata[i*3+2] = lumdata[i];
}
lumdata = NULL;
}
}
/*if we're relighting, make sure there's the proper lux data to be updated*/
if (lightmodel == loadmodel && r_deluxemapping.ival && !luxdata)
{
int i;
luxdata = Hunk_AllocName(samples*3, "lux data");
for (i = 0; i < samples; i++)
{
litdata[i*3+0] = 0.5f*255;
litdata[i*3+0] = 0.5f*255;
litdata[i*3+0] = 255;
}
}
#endif
if (loadmodel->lightdata)
if (luxdata && luxtmp)
{
if ((loadmodel->engineflags & MDLF_RGBLIGHTING) && r_lightmap_saturation.value != 1.0f)
loadmodel->engineflags |= MDLF_RGBLIGHTING;
loadmodel->deluxdata = Hunk_AllocName(samples*3, "lit data");
memcpy(loadmodel->deluxdata, luxdata, samples*3);
}
else if (luxdata)
{
// desaturate lightmap according to cvar
SaturateR8G8B8(loadmodel->lightdata, l->filelen, r_lightmap_saturation.value);
loadmodel->deluxdata = luxdata;
}
return;
if (litdata && littmp)
{
loadmodel->engineflags |= MDLF_RGBLIGHTING;
loadmodel->lightdata = Hunk_AllocName(samples*3, "lit data");
/*the memcpy is below*/
samples*=3;
}
else if (litdata)
{
loadmodel->engineflags |= MDLF_RGBLIGHTING;
loadmodel->lightdata = litdata;
samples*=3;
}
else if (lumdata)
{
loadmodel->engineflags &= ~MDLF_RGBLIGHTING;
loadmodel->lightdata = Hunk_AllocName(samples, "lit data");
litdata = lumdata;
}
loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);
{
int i;
qbyte *in, *out;
in = mod_base + l->fileofs;
/*apply lightmap gamma to the entire lightmap*/
out = loadmodel->lightdata;
for (i = 0; i < l->filelen; i++)
while(samples-- > 0)
{
*out++ = lmgamma[*in++];
*out++ = lmgamma[*litdata++];
}
if ((loadmodel->engineflags & MDLF_RGBLIGHTING) && r_lightmap_saturation.value != 1.0f)
SaturateR8G8B8(loadmodel->lightdata, l->filelen, r_lightmap_saturation.value);
}
//memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
}
/*
=================
@ -3159,6 +3204,7 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer)
for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
((int *)header)[i] = LittleLong ( ((int *)header)[i]);
Q1BSPX_Setup(loadmodel, mod_base, com_filesize, header->lumps, HEADER_LUMPS);
// checksum all of the map, except for entities
mod->checksum = 0;
@ -3258,6 +3304,7 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer)
return false;
}
Q1BSP_LoadBrushes(mod);
Q1BSP_SetModelFuncs(mod);
mod->funcs.LightPointValues = GLQ1BSP_LightPointValues;
mod->funcs.StainNode = Q1BSP_StainNode;
@ -3856,7 +3903,7 @@ static void LoadDoomSpriteFrame(char *imagename, mspriteframedesc_t *pdesc, int
}
palette = COM_LoadTempFile("wad/playpal");
header = (doomimage_t *)COM_LoadTempFile2(imagename);
header = (doomimage_t *)COM_LoadTempMoreFile(imagename);
data = (qbyte *)header;
pframe->up = +header->ypos;
pframe->down = -header->height + header->ypos;

View file

@ -419,6 +419,18 @@ typedef struct msurface_s
#endif
} msurface_t;
typedef struct mbrush_s
{
struct mbrush_s *next;
unsigned int contents;
int numplanes;
struct mbrushplane_s
{
vec3_t normal;
float dist;
} planes[1];
} mbrush_t;
typedef struct mnode_s
{
// common with leaf
@ -429,6 +441,7 @@ typedef struct mnode_s
float minmaxs[6]; // for bounding box culling
struct mnode_s *parent;
struct mbrush_s *brushes;
// node specific
mplane_t *plane;
@ -453,6 +466,7 @@ typedef struct mleaf_s
float minmaxs[6]; // for bounding box culling
struct mnode_s *parent;
struct mbrush_s *brushes;
// leaf specific
qbyte *compressed_vis;
@ -506,7 +520,10 @@ typedef struct hull_s
void Q1BSP_CheckHullNodes(hull_t *hull);
void Q1BSP_SetModelFuncs(struct model_s *mod);
void Q1BSP_LoadBrushes(struct model_s *model);
void Q1BSP_Init(void);
void *Q1BSPX_FindLump(char *lumpname, int *lumpsize);
void Q1BSPX_Setup(struct model_s *mod, char *filebase, unsigned int filelen, lump_t *lumps, int numlumps);
int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangent2, float size, float **out);
@ -953,6 +970,7 @@ typedef struct model_s
#define MDLF_BOLT 0x080 // doesn't produce shadows
#define MDLF_NOTREPLACEMENTS 0x100 // can be considered a cheat, disable texture replacements
#define MDLF_EZQUAKEFBCHEAT 0x200 // this is a blatent cheat, one that can disadvantage us fairly significantly if we don't support it.
#define MDLF_HASBRUSHES 0x400 // q1bsp has brush info for more precise traceboxes
//============================================================================
/*

View file

@ -223,6 +223,56 @@ void GL_SetupSceneProcessingTextures (void)
}
void R_RotateForEntity (float *m, float *modelview, const entity_t *e, const model_t *mod)
{
if (e->flags & Q2RF_WEAPONMODEL && r_refdef.currentplayernum>=0)
{
entity_t *view = &cl.viewent[r_refdef.currentplayernum];
float em[16];
float vm[16];
vm[0] = view->axis[0][0];
vm[1] = view->axis[0][1];
vm[2] = view->axis[0][2];
vm[3] = 0;
vm[4] = view->axis[1][0];
vm[5] = view->axis[1][1];
vm[6] = view->axis[1][2];
vm[7] = 0;
vm[8] = view->axis[2][0];
vm[9] = view->axis[2][1];
vm[10] = view->axis[2][2];
vm[11] = 0;
vm[12] = view->origin[0];
vm[13] = view->origin[1];
vm[14] = view->origin[2];
vm[15] = 1;
em[0] = e->axis[0][0];
em[1] = e->axis[0][1];
em[2] = e->axis[0][2];
em[3] = 0;
em[4] = e->axis[1][0];
em[5] = e->axis[1][1];
em[6] = e->axis[1][2];
em[7] = 0;
em[8] = e->axis[2][0];
em[9] = e->axis[2][1];
em[10] = e->axis[2][2];
em[11] = 0;
em[12] = e->origin[0];
em[13] = e->origin[1];
em[14] = e->origin[2];
em[15] = 1;
Matrix4_Multiply(vm, em, m);
}
else
{
m[0] = e->axis[0][0];
m[1] = e->axis[0][1];
@ -243,6 +293,7 @@ void R_RotateForEntity (float *m, float *modelview, const entity_t *e, const mod
m[13] = e->origin[1];
m[14] = e->origin[2];
m[15] = 1;
}
if (e->scale != 1 && e->scale != 0) //hexen 2 stuff
{
@ -298,22 +349,8 @@ void R_RotateForEntity (float *m, float *modelview, const entity_t *e, const mod
VectorScale((m+8), mod->clampscale, (m+8));
}
if (e->flags & Q2RF_WEAPONMODEL && r_refdef.currentplayernum>=0)
{
/*FIXME: no bob*/
float simpleview[16];
vec3_t ang;
ang[0] = 0;
ang[1] = 0;
ang[2] = gl_screenangle.value;
Matrix4x4_CM_ModelViewMatrix(simpleview, ang, vec3_origin);
Matrix4_Multiply(simpleview, m, modelview);
}
else
{
Matrix4_Multiply(r_refdef.m_view, m, modelview);
}
}
//==================================================================================

View file

@ -2908,7 +2908,7 @@ void Sh_DrawLights(qbyte *vis, batch_t **mbatches)
if (dl->flags & LFLAG_CREPUSCULAR)
Sh_DrawCrepuscularLight(dl, colour, mbatches);
else if (((!dl->die)?!r_shadow_realtime_world_shadows.ival:!r_shadow_realtime_dlight_shadows.ival) || dl->flags & LFLAG_NOSHADOWS)
else if (((i >= RTL_FIRST)?!r_shadow_realtime_world_shadows.ival:!r_shadow_realtime_dlight_shadows.ival) || dl->flags & LFLAG_NOSHADOWS)
{
Sh_DrawShadowlessLight(dl, colour, vis);
}

View file

@ -220,112 +220,7 @@ void GLVID_ShiftPalette (unsigned char *palette)
}
}
void Sys_SendKeyEvents(void)
{
}
void GLVID_SetCaption(char *caption)
{
}
extern qboolean mouse_active;
cvar_t m_filter = CVARF("m_filter", "1", CVAR_ARCHIVE);
extern cvar_t _windowed_mouse;
float mouse_x, mouse_y;
float old_mouse_x, old_mouse_y;
void IN_Shutdown(void)
{
}
void IN_ReInit()
{
Cvar_Register (&m_filter, "input controls");
}
void IN_Init(void)
{
IN_ReInit();
}
void IN_Commands(void)
{
}
void IN_Move (float *movements, int pnum)
{
extern int mousecursor_x, mousecursor_y;
extern int mousemove_x, mousemove_y;
if (pnum != 0)
return; //we're lazy today.
if (m_filter.value)
{
mouse_x = (mouse_x + old_mouse_x) * 0.5;
mouse_y = (mouse_y + old_mouse_y) * 0.5;
}
old_mouse_x = mouse_x;
old_mouse_y = mouse_y;
if(in_xflip.value) mouse_x *= -1;
if (Key_MouseShouldBeFree())
{
mousemove_x += mouse_x;
mousemove_y += mouse_y;
if (mousecursor_y<0)
mousecursor_y=0;
if (mousecursor_x<0)
mousecursor_x=0;
if (mousecursor_x >= vid.width)
mousecursor_x = vid.width - 1;
if (mousecursor_y >= vid.height)
mousecursor_y = vid.height - 1;
mouse_x = mouse_y = 0;
#ifdef VM_UI
UI_MousePosition(mousecursor_x, mousecursor_y);
#endif
}
mouse_x *= sensitivity.value;
mouse_y *= sensitivity.value;
if ( (in_strafe.state[pnum] & 1) || (lookstrafe.value && (in_mlook.state[pnum] & 1) ))
{
if (movements)
movements[1] += m_side.value * mouse_x;
}
else
{
cl.viewanglechange[pnum][YAW] -= m_yaw.value * mouse_x;
}
if (in_mlook.state[pnum] & 1)
V_StopPitchDrift (pnum);
if ( (in_mlook.state[pnum] & 1) && !(in_strafe.state[pnum] & 1))
{
cl.viewanglechange[pnum][PITCH] += m_pitch.value * mouse_y;
}
else
{
if (movements)
{
if ((in_strafe.state[pnum] & 1) && noclip_anglehack)
movements[2] -= m_forward.value * mouse_y;
else
movements[0] -= m_forward.value * mouse_y;
}
}
mouse_x = mouse_y = 0.0;
}

View file

@ -1857,7 +1857,7 @@ static void Doom_LoadVerticies(char *name)
std = (void *)COM_LoadTempFile (va("%s.vertexes", name));
stdc = com_filesize/sizeof(*std);
gl2 = (void *)COM_LoadTempFile2 (va("%s.gl_vert", name));
gl2 = (void *)COM_LoadTempMoreFile (va("%s.gl_vert", name));
if (!gl2)
{
glc = 0;

View file

@ -2958,7 +2958,7 @@ static void QCBUILTIN PF_LocalSound(progfuncs_t *prinst, struct globalvars_s *pr
if (!isDedicated)
{
if ((sfx = S_PrecacheSound(s)))
S_StartSound(cl.playernum[0], chan, sfx, cl.simorg[0], vol, 0.0, 0);
S_StartSound(cl.playernum[0], chan, sfx, cl.simorg[0], vol, 0.0, 0, 0);
}
#endif
};

View file

@ -287,7 +287,7 @@ typedef struct
double senttime; //time we sent this frame to the client, for ping calcs
int sequence; //the outgoing sequence - without mask, meaning we know if its current or stale
float ping_time; //how long it took for the client to ack it, may be negativ
int move_msecs; //
float move_msecs; //
int packetsizein; //amount of data received for this frame
int packetsizeout; //amount of data that was sent in the frame
vec3_t playerpositions[MAX_CLIENTS]; //where each player was in this frame, for antilag
@ -552,6 +552,10 @@ typedef struct client_s
struct client_s *controller; /*first in splitscreen chain, NULL=nosplitscreen*/
struct client_s *controlled; /*next in splitscreen chain*/
/*these are the current rates*/
float ratetime;
float inrate;
float outrate;
int rate;
int drate;

View file

@ -2871,7 +2871,7 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs,
{
//pvs and clent can be null, but only if the other is also null
int e, i;
edict_t *ent;
edict_t *ent, *trackent;
entity_state_t *state;
#define DEPTHOPTIMISE
#ifdef DEPTHOPTIMISE
@ -2882,6 +2882,11 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs,
globalvars_t *pr_globals = PR_globals(svprogfuncs, PR_CURRENT);
int pvsflags;
if (client->spectator)
trackent = EDICT_NUM(svprogfuncs, client->spec_track);
else
trackent = PROG_TO_EDICT(svprogfuncs, clent->xv->view2);
if (client->viewent
#ifdef NQPROT
&& ISQWCLIENT(client)
@ -2967,7 +2972,7 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs,
continue;
pvsflags = PVSF_IGNOREPVS;
}
else if (ent == clent)
else if (ent == clent || ent == trackent)
{
pvsflags = PVSF_IGNOREPVS;
}
@ -2978,7 +2983,7 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs,
continue;
pvsflags = ent->xv->pvsflags;
if (pvs && ent != clent) //self doesn't get a pvs test, to cover teleporters
if (pvs) //self doesn't get a pvs test, to cover teleporters
{
if ((int)ent->v->effects & EF_NODEPTHTEST)
{

View file

@ -394,8 +394,21 @@ void SV_CalcPHS (void)
rowwords = (num+31)>>5;
rowbytes = rowwords*4;
if (developer.value)
Con_TPrintf (STL_BUILDINGPHS);
if (!sv_calcphs.ival || (sv_calcphs.ival == 2 && (rowbytes*num >= 0x100000 || (!deathmatch.ival && !coop.ival))))
{
sv.pvs = Hunk_AllocName (rowbytes*num, "pvs vis");
scan = sv.pvs;
for (i=0 ; i<num ; i++, scan+=rowbytes)
{
lf = sv.world.worldmodel->funcs.LeafPVS(sv.world.worldmodel, i, scan, rowbytes);
if (lf != scan)
memcpy (scan, lf, rowbytes);
}
Con_DPrintf("Skipping PHS\n");
sv.phs = NULL;
return;
}
sv.pvs = Hunk_AllocName (rowbytes*num, "phs vis");
scan = sv.pvs;
@ -415,13 +428,8 @@ void SV_CalcPHS (void)
}
}
}
if (!sv_calcphs.ival || (sv_calcphs.ival == 2 && (rowbytes*num >= 0x100000 || (!deathmatch.ival && !coop.ival))))
{
Con_DPrintf("Skipping PHS\n");
sv.phs = NULL;
return;
}
if (developer.value)
Con_TPrintf (STL_BUILDINGPHS);
/*this routine takes an exponential amount of time, so cache it if its too big*/
if (rowbytes*num >= 0x100000)
@ -753,14 +761,6 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us
Cvar_ApplyLatches(CVAR_LATCH);
//work out the gamespeed
sv.gamespeed = sv_gamespeed.value;
Info_SetValueForStarKey(svs.info, "*gamespeed", va("%i", (int)(sv.gamespeed*100)), MAX_SERVERINFO_STRING);
sv.gamespeed = atof(Info_ValueForKey(svs.info, "*gamespeed"))/100;
if (sv.gamespeed < 0.1 || sv.gamespeed == 1)
{
sv.gamespeed = 1;
Info_SetValueForStarKey(svs.info, "*gamespeed", "", MAX_SERVERINFO_STRING);
}
//reset the server time.
sv.time = 0.01; //some progs don't like time starting at 0.
//cos of spawn funcs like self.nextthink = time...

View file

@ -3808,6 +3808,27 @@ float SV_Frame (void)
oldpaused = sv.paused;
}
//work out the gamespeed
if (sv.gamespeed != sv_gamespeed.value)
{
char *newspeed;
sv.gamespeed = sv_gamespeed.value;
if (sv.gamespeed < 0.1 || sv.gamespeed == 1)
sv_gamespeed.value = sv.gamespeed = 1;
if (sv.gamespeed == 1)
newspeed = "";
else
newspeed = va("%g", sv.gamespeed*100);
Info_SetValueForStarKey(svs.info, "*gamespeed", newspeed, MAX_SERVERINFO_STRING);
SV_SendServerInfoChange("*gamespeed", newspeed);
//correct sv.starttime
sv.starttime = Sys_DoubleTime() - (sv.time/sv.gamespeed);
}
// decide the simulation time
{
oldtime = sv.time;
@ -3824,7 +3845,7 @@ float SV_Frame (void)
if (sv.paused && sv.time > 1.5)
{
sv.starttime += sv.time - oldtime; //move the offset
sv.starttime += (sv.time - oldtime)/sv.gamespeed; //move the offset
sv.time = oldtime; //and keep time as it was.
}
}
@ -4653,7 +4674,7 @@ void SV_ExtractFromUserinfo (client_t *cl)
if (strlen(val))
cl->rate = atoi(val);
else
cl->rate = 2500;
cl->rate = ISNQCLIENT(cl)?10000:2500;
val = Info_ValueForKey (cl->userinfo, "drate");
if (strlen(val))

View file

@ -2337,6 +2337,15 @@ void SV_SendClientMessages (void)
}
c->waschoked = false;
if (sv.time > c->ratetime + 1)
{
c->inrate = c->netchan.bytesin / (sv.time - c->ratetime);
c->outrate = c->netchan.bytesout / (sv.time - c->ratetime);
c->netchan.bytesin = 0;
c->netchan.bytesout = 0;
c->ratetime = sv.time;
}
if (c->state == cs_spawned)
SV_SendClientDatagram (c);
else

View file

@ -241,7 +241,7 @@ Loads the game dll
*/
void *Sys_GetGameAPI (void *parms)
{
void *(*GetGameAPI) (void *);
void *(VARGS *GetGameAPI) (void *);
char name[MAX_OSPATH];
char *path;
char cwd[MAX_OSPATH];

View file

@ -3486,7 +3486,11 @@ void SV_Rate_f (void)
{
if (Cmd_Argc() != 2)
{
SV_ClientPrintf (host_client, PRINT_HIGH, "Effective rate %i\n", SV_RateForClient(host_client));
int rate = SV_RateForClient(host_client);
if (!rate)
SV_ClientPrintf (host_client, PRINT_HIGH, "Effective rate is unlimited\n", rate);
else
SV_ClientPrintf (host_client, PRINT_HIGH, "Effective rate %i\n", rate);
return;
}
@ -4280,7 +4284,7 @@ void Cmd_FPSList_f(void)
int frames;
int inbytes;
int outbytes;
int msecs;
float msecs;
for (c = 0; c < sv.allocated_client_slots; c++)
@ -4328,9 +4332,9 @@ void Cmd_FPSList_f(void)
}
if (frames)
SV_ClientPrintf(host_client, PRINT_HIGH, "%s: %ffps (min%.2f max %.2f), in: %.2fbps, out: %.2fbps\n", cl->name, ftime/frames, minf, maxf, (1000.0f*inbytes)/msecs, (1000.0f*outbytes)/msecs);
SV_ClientPrintf(host_client, PRINT_HIGH, "%s: %gfps (min%g max %g), in: %ibps, out: %ibps\n", cl->name, ftime/frames, minf, maxf, (int)cl->inrate, (int)cl->outrate);
else
SV_ClientPrintf(host_client, PRINT_HIGH, "%s: no information available\n", cl->name);
SV_ClientPrintf(host_client, PRINT_HIGH, "%s: unknown framerate, in: %ibps, out: %ibps\n", cl->name, (int)cl->inrate, (int)cl->outrate);
}
}
@ -6674,6 +6678,7 @@ void SVNQ_ReadClientMove (usercmd_t *move)
if (cltime < sv.time - 2) //if you do lag more than this, you won't get your free time.
cltime = sv.time - 2;
timesincelast = cltime - move->fservertime;
move->fservertime = cltime;
move->servertime = move->fservertime;
@ -6693,10 +6698,8 @@ void SVNQ_ReadClientMove (usercmd_t *move)
move->sidemove = MSG_ReadShort ();
move->upmove = MSG_ReadShort ();
move->msec=timesincelast*1000;//MSG_ReadFloat;
frame->move_msecs = move->msec;
move->msec=timesincelast*1000;
frame->move_msecs = timesincelast*1000;
// read buttons
if (host_client->protocol == SCP_DARKPLACES6 || host_client->protocol == SCP_DARKPLACES7)

View file

@ -1817,6 +1817,7 @@ qboolean Mod_LoadBrushModel (model_t *mod, void *buffer)
return false;
}
Q1BSP_LoadBrushes(mod);
Q1BSP_SetModelFuncs(mod);
if (mod->surfaces && mod->lightdata)

View file

@ -343,6 +343,7 @@ static qboolean VARGS PFQ2_inPVS (vec3_t p1, vec3_t p2)
int area1, area2;
qbyte *mask;
//FIXME: requires q2/q3 bsp
leafnum = CM_PointLeafnum (sv.world.worldmodel, p1);
cluster = CM_LeafCluster (sv.world.worldmodel, leafnum);
area1 = CM_LeafArea (sv.world.worldmodel, leafnum);
@ -373,6 +374,7 @@ static qboolean VARGS PFQ2_inPHS (vec3_t p1, vec3_t p2)
int area1, area2;
qbyte *mask;
//FIXME: requires q2/q3 bsp
leafnum = CM_PointLeafnum (sv.world.worldmodel, p1);
cluster = CM_LeafCluster (sv.world.worldmodel, leafnum);
area1 = CM_LeafArea (sv.world.worldmodel, leafnum);
@ -391,6 +393,7 @@ static qboolean VARGS PFQ2_inPHS (vec3_t p1, vec3_t p2)
qboolean VARGS PFQ2_AreasConnected(int area1, int area2)
{
//FIXME: requires q2/q3 bsp
return CM_AreasConnected(sv.world.worldmodel, area1, area2);
}
@ -536,19 +539,26 @@ static q2trace_t VARGS SVQ2_Trace (vec3_t start, vec3_t mins, vec3_t maxs, vec3_
{
q2trace_t ret;
trace_t tr;
static vec3_t nullvec;
if (!mins)
mins = nullvec;
mins = vec3_origin;
if (!maxs)
maxs = nullvec;
maxs = vec3_origin;
tr = WorldQ2_Move(&sv.world, start, mins, maxs, end, contentmask, passedict);
memcpy(&ret, &tr, sizeof(q2trace_t));
ret.allsolid = tr.allsolid;
ret.startsolid = tr.startsolid;
ret.contents = tr.contents;
ret.surface = tr.surface;
ret.fraction = tr.fraction;
VectorCopy(tr.endpos, ret.endpos);
VectorCopy(tr.plane.normal, ret.plane.normal);
ret.plane.dist = tr.plane.dist;
// memcpy(&ret, &tr, sizeof(q2trace_t));
return ret;
}
static int VARGS SVQ2_PointContents (vec3_t p)
{
q2trace_t tr = SVQ2_Trace(p, NULL, NULL, p, NULL, ~0);
q2trace_t tr = SVQ2_Trace(p, vec3_origin, vec3_origin, p, NULL, ~0);
return tr.contents;
// return CM_PointContents(p, 0);
}

View file

@ -1869,7 +1869,8 @@ trace_t WorldQ2_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t
memset ( &clip, 0, sizeof ( moveclip_t ) );
// clip to world
clip.trace = CM_BoxTrace(w->worldmodel, start, end, mins, maxs, hitcontentsmask);//SVQ2_ClipMoveToEntity ( ge->edicts, start, mins, maxs, end );
w->worldmodel->funcs.NativeTrace(w->worldmodel, 0, 0, NULL, start, end, mins, maxs, hitcontentsmask, &clip.trace);
// clip.trace = CM_BoxTrace(w->worldmodel, start, end, mins, maxs, hitcontentsmask);//SVQ2_ClipMoveToEntity ( ge->edicts, start, mins, maxs, end );
clip.trace.ent = ge->edicts;
if (clip.trace.fraction == 0)