/*
========================
idParallelJobManagerLocal::Init
========================
*/
void idParallelJobManagerLocal::Init()
{
	// on consoles this will have specific cores for the threads, but on PC they will all be CORE_ANY
	core_t cores[] = JOB_THREAD_CORES;
	assert( sizeof( cores ) / sizeof( cores[0] ) >= MAX_JOB_THREADS );
	
	for( int i = 0; i < MAX_JOB_THREADS; i++ )
	{
		threads[i].Start( cores[i], i );
	}
	maxThreads = jobs_numThreads.GetInteger();
	
	Sys_CPUCount( numPhysicalCpuCores, numLogicalCpuCores, numCpuPackages );
}
Пример #2
0
void idGameEdit::RecordPlayback( const usercmd_t &cmd, idEntity *source )
{
    // Not recording - so instantly exit
    if( !g_recordPlayback.GetInteger() && !gamePlayback )
    {
        return;
    }

    if( !gamePlayback )
    {
        gamePlayback = new rvGamePlayback();
    }

    if( g_recordPlayback.GetInteger() )
    {
        gamePlayback->RecordData( cmd, source );
    }
    else
    {
        delete gamePlayback;
        gamePlayback = NULL;
    }
}
Пример #3
0
/*
========================
idResolutionScale::GetCurrentResolutionScale
========================
*/
void idResolutionScale::GetCurrentResolutionScale( float& x, float& y )
{
	assert( currentResolution >= MINIMUM_RESOLUTION_SCALE );
	assert( currentResolution <= MAXIMUM_RESOLUTION_SCALE );
	
	x = MAXIMUM_RESOLUTION_SCALE;
	y = MAXIMUM_RESOLUTION_SCALE;

	// foresthale 2014-05-28: don't allow resolution scaling with editors, we don't really care about framerate and we don't refresh constantly anyway
	if (com_editors)
		return;

	switch( rs_enable.GetInteger() )
	{
		case 0:
			return;
		case 1:
			x = currentResolution;
			break;
		case 2:
			y = currentResolution;
			break;
		case 3:
		{
			const float middle = ( MINIMUM_RESOLUTION_SCALE + MAXIMUM_RESOLUTION_SCALE ) * 0.5f;
			if( currentResolution >= middle )
			{
				// First scale horizontally from max to min
				x = MINIMUM_RESOLUTION_SCALE + ( currentResolution - middle ) * 2.0f;
			}
			else
			{
				// Then scale vertically from max to min
				x = MINIMUM_RESOLUTION_SCALE;
				y = MINIMUM_RESOLUTION_SCALE + ( currentResolution - MINIMUM_RESOLUTION_SCALE ) * 2.0f;
			}
			break;
		}
	}
	float forceFrac = rs_forceFractionX.GetFloat();
	if( forceFrac > 0.0f && forceFrac <= MAXIMUM_RESOLUTION_SCALE )
	{
		x = forceFrac;
	}
	forceFrac = rs_forceFractionY.GetFloat();
	if( forceFrac > 0.0f && forceFrac <= MAXIMUM_RESOLUTION_SCALE )
	{
		y = forceFrac;
	}
}
/*
========================
idLobbyBackendDirect::GetConnectInfo
========================
*/
lobbyConnectInfo_t idLobbyBackendDirect::GetConnectInfo() {
	lobbyConnectInfo_t connectInfo;

	// If we aren't the host, this lobby should have been joined through JoinFromConnectInfo
	if ( IsHost() ) {
		// If we are the host, give them our ip address
		const char * ip = Sys_GetLocalIP( 0 );
		Sys_StringToNetAdr( ip, &address, false );
		address.port = net_port.GetInteger();
	}

	connectInfo.netAddr = address;

	return connectInfo;
}
Пример #5
0
void idMultiplayerGame::ReceiveAndPlayVoiceData( const idBitMsg &inMsg )
{
	int		clientNum;

	if( !gameLocal.serverInfo.GetBool( "si_voiceChat" ) )
	{
		return;
	}
	
	clientNum = inMsg.ReadByte();
	soundSystem->PlayVoiceData( clientNum, inMsg.GetReadData(), inMsg.GetRemainingData() );
	if( g_voiceChatDebug.GetInteger() & 4 )
	{
		common->Printf( "VC: Playing %d bytes\n", inMsg.GetRemainingData() );
	}
}
/*
========================
idLobbyBackendDirect::JoinFromConnectInfo
========================
*/
void idLobbyBackendDirect::JoinFromConnectInfo( const lobbyConnectInfo_t& connectInfo )
{
	if( lobbyToSessionCB->CanJoinLocalHost() )
	{
		Sys_StringToNetAdr( "localhost", &address, true );
		address.port = net_port.GetInteger();
	}
	else
	{
		address = connectInfo.netAddr;
	}
	
	state		= STATE_READY;
	isLocal		= false;
	isHost		= false;
}
Пример #7
0
/*
========================
idResolutionScale::GetCurrentResolutionScale
========================
*/
void idResolutionScale::GetCurrentResolutionScale( float& x, float& y )
{
	assert( currentResolution >= MINIMUM_RESOLUTION_SCALE );
	assert( currentResolution <= MAXIMUM_RESOLUTION_SCALE );
	
	x = MAXIMUM_RESOLUTION_SCALE;
	y = MAXIMUM_RESOLUTION_SCALE;
	switch( rs_enable.GetInteger() )
	{
		case 0:
			return;
		case 1:
			x = currentResolution;
			break;
		case 2:
			y = currentResolution;
			break;
		case 3:
		{
			const float middle = ( MINIMUM_RESOLUTION_SCALE + MAXIMUM_RESOLUTION_SCALE ) * 0.5f;
			if( currentResolution >= middle )
			{
				// First scale horizontally from max to min
				x = MINIMUM_RESOLUTION_SCALE + ( currentResolution - middle ) * 2.0f;
			}
			else
			{
				// Then scale vertically from max to min
				x = MINIMUM_RESOLUTION_SCALE;
				y = MINIMUM_RESOLUTION_SCALE + ( currentResolution - MINIMUM_RESOLUTION_SCALE ) * 2.0f;
			}
			break;
		}
	}
	float forceFrac = rs_forceFractionX.GetFloat();
	if( forceFrac > 0.0f && forceFrac <= MAXIMUM_RESOLUTION_SCALE )
	{
		x = forceFrac;
	}
	forceFrac = rs_forceFractionY.GetFloat();
	if( forceFrac > 0.0f && forceFrac <= MAXIMUM_RESOLUTION_SCALE )
	{
		y = forceFrac;
	}
}
Пример #8
0
static HGLRC CreateOpenGLContextOnDC( const HDC hdc, const bool debugContext ) {
    HGLRC m_hrc = NULL;
    int useOpenGL32 = r_useOpenGL32.GetInteger();

    for ( int i = 0; i < 2; i++ ) {
        const int glMajorVersion = ( useOpenGL32 != 0 ) ? 3 : 2;
        const int glMinorVersion = ( useOpenGL32 != 0 ) ? 2 : 0;
        const int glDebugFlag = debugContext ? WGL_CONTEXT_DEBUG_BIT_ARB : 0;
        const int glProfileMask = ( useOpenGL32 != 0 ) ? WGL_CONTEXT_PROFILE_MASK_ARB : 0;
        const int glProfile = ( useOpenGL32 == 1 ) ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : ( ( useOpenGL32 == 2 ) ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : 0 );
        const int attribs[] =
        {
            WGL_CONTEXT_MAJOR_VERSION_ARB,	glMajorVersion,
            WGL_CONTEXT_MINOR_VERSION_ARB,	glMinorVersion,
            WGL_CONTEXT_FLAGS_ARB,			glDebugFlag,
            glProfileMask,					glProfile,
            0
        };

        m_hrc = wglCreateContextAttribsARB( hdc, 0, attribs );
        if ( m_hrc != NULL ) {
            idLib::Printf( "created OpenGL %d.%d context\n", glMajorVersion, glMinorVersion );
            break;
        }

        idLib::Printf( "failed to create OpenGL %d.%d context\n", glMajorVersion, glMinorVersion );
        useOpenGL32 = 0;	// fall back to OpenGL 2.0
    }

    if ( m_hrc == NULL ) {
        int	err = GetLastError();
        switch( err ) {
        case ERROR_INVALID_VERSION_ARB:
            idLib::Printf( "ERROR_INVALID_VERSION_ARB\n" );
            break;
        case ERROR_INVALID_PROFILE_ARB:
            idLib::Printf( "ERROR_INVALID_PROFILE_ARB\n" );
            break;
        default:
            idLib::Printf( "unknown error: 0x%x\n", err );
            break;
        }
    }
    return m_hrc;
}
Пример #9
0
/*
========================
idSoundWorldLocal::UnPause
========================
*/
void idSoundWorldLocal::UnPause() {
	if ( isPaused ) {
		isPaused = false;
		accumulatedPauseTime += soundSystemLocal.SoundTime() - pausedTime;
		pauseFade.SetVolume( DB_SILENCE );
		pauseFade.Fade( 0.0f, s_unpauseFadeInTime.GetInteger(), GetSoundTime() );

		// just unpause all unmutable voices (normally just voice overs)
		for ( int e = emitters.Num() - 1; e > 0; e-- ) {
			for ( int i = 0; i < emitters[e]->channels.Num(); i++ ) {
				idSoundChannel * channel = emitters[e]->channels[i];
				if ( !channel->CanMute() && channel->hardwareVoice != NULL ) {
					channel->hardwareVoice->UnPause();
				}
			}
		}
	}
}
/*
========================
idParallelJobManagerLocal::Submit
========================
*/
void idParallelJobManagerLocal::Submit( idParallelJobList_Threads* jobList, int parallelism )
{
	if( jobs_numThreads.IsModified() )
	{
		maxThreads = idMath::ClampInt( 0, MAX_JOB_THREADS, jobs_numThreads.GetInteger() );
		jobs_numThreads.ClearModified();
	}
	
	// determine the number of threads to use
	int numThreads = maxThreads;
	if( parallelism == JOBLIST_PARALLELISM_DEFAULT )
	{
		numThreads = maxThreads;
	}
	else if( parallelism == JOBLIST_PARALLELISM_MAX_CORES )
	{
		numThreads = numLogicalCpuCores;
	}
	else if( parallelism == JOBLIST_PARALLELISM_MAX_THREADS )
	{
		numThreads = MAX_JOB_THREADS;
	}
	else if( parallelism > MAX_JOB_THREADS )
	{
		numThreads = MAX_JOB_THREADS;
	}
	else
	{
		numThreads = parallelism;
	}
	
	if( numThreads <= 0 )
	{
		threadJobListState_t state( jobList->GetVersion() );
		jobList->RunJobs( 0, state, false );
		return;
	}
	
	for( int i = 0; i < numThreads; i++ )
	{
		threads[i].AddJobList( jobList );
		threads[i].SignalWork();
	}
}
/*
========================
idLobbyBackendDirect::JoinFromConnectInfo
========================
*/
void idLobbyBackendDirect::JoinFromConnectInfo( const lobbyConnectInfo_t& connectInfo )
{
	if( lobbyToSessionCB->CanJoinLocalHost() )
	{
		// TODO: "CanJoinLocalHost" == *must* join LocalHost ?!
		Sys_StringToNetAdr( "localhost", &address, true );
		address.port = net_port.GetInteger();
		NET_VERBOSE_PRINT( "NET: idLobbyBackendDirect::JoinFromConnectInfo(): canJoinLocalHost\n" );
	}
	else
	{
		address = connectInfo.netAddr;
		NET_VERBOSE_PRINT( "NET: idLobbyBackendDirect::JoinFromConnectInfo(): %s\n", Sys_NetAdrToString( address ) );
	}
	
	state		= STATE_READY;
	isLocal		= false;
	isHost		= false;
}
Пример #12
0
/*
==============================================
idSWFTextInstance::UpdateSubtitle
==============================================
*/
bool idSWFTextInstance::UpdateSubtitle( int time ) {

	if ( subForceKillQueued ) {
		subForceKillQueued = false;
		subForceKill = true;
		subKillTimeDelay = time + swf_subtitleExtraTime.GetInteger();
	}

	if ( subUpdating && !subForceKill ) {
		if ( ( time >= subSwitchTime && !subNeedsSwitch ) || ( !subNeedsSwitch && subInitialLine ) ) {
			//idLib::Printf( "SWITCH TIME %d / %d \n", time, subSwitchTime );

			if ( subInitialLine && subtitleTimingInfo.Num() > 0 ) {
				if ( subStartTime == -1 ) {
					subStartTime = time - 600;
				}
				if ( time < subStartTime + subtitleTimingInfo[0].startTime ) {
					return true;
				} else {
					text = subtitleText;//subtitleText = "";
					subInitialLine = false;
				}				
			}

			if ( subNextStartIndex + 1 >= text.Length( ) ) {
				subForceKillQueued = true;
			} else {
				subCharStartIndex = subNextStartIndex;
				//subtitleText.CopyRange( text, subCharStartIndex, subCharEndIndex );
				subNeedsSwitch = true;
			}
		}
	}

	if ( subForceKill ) {
		if ( time >= subKillTimeDelay ) {
			subForceKill = false;
			return false;
		}
	}

	return true;
}
/*
========================
idMenuScreen_Shell_SystemOptions::idMenuDataSource_SystemSettings::IsRestartRequired
========================
*/
bool idMenuScreen_Shell_SystemOptions::idMenuDataSource_SystemSettings::IsRestartRequired() const
{
	if( originalAntialias != r_antiAliasing.GetInteger() )
	{
		return true;
	}
	
	if( originalFramerate != com_engineHz.GetInteger() )
	{
		return true;
	}
	
	if( originalShadowMapping != r_useShadowMapping.GetInteger() )
	{
		return true;
	}
	
	return false;
}
/*
===============
idCommonLocal::SendSnapshots
===============
*/
void idCommonLocal::SendSnapshots() {
    if ( !mapSpawned ) {
        return;
    }
    int currentTime = Sys_Milliseconds();
    if ( currentTime < nextSnapshotSendTime ) {
        return;
    }
    idLobbyBase & lobby = session->GetActingGameStateLobbyBase();
    if ( !lobby.IsHost() ) {
        return;
    }
    if ( !lobby.HasActivePeers() ) {
        return;
    }
    idSnapShot ss;
    game->ServerWriteSnapshot( ss );

    session->SendSnapshot( ss );
    nextSnapshotSendTime = MSEC_ALIGN_TO_FRAME( currentTime + net_snapRate.GetInteger() );
}
/*
========================
idMenuScreen_Shell_SystemOptions::idMenuDataSource_SystemSettings::GetField
========================
*/
idSWFScriptVar idMenuScreen_Shell_SystemOptions::idMenuDataSource_SystemSettings::GetField( const int fieldIndex ) const {
    switch ( fieldIndex ) {
    case SYSTEM_FIELD_FULLSCREEN: {
        const int fullscreen = r_fullscreen.GetInteger();
        const int vidmode = r_vidMode.GetInteger();
        if ( fullscreen == 0 ) {
            return "#str_swf_disabled";
        }
        if ( fullscreen < 0 || vidmode < 0 || vidmode >= modeList.Num() ) {
            return "???";
        }
        if ( modeList[vidmode].displayHz == 60 ) {
            return va( "%4i x %4i", modeList[vidmode].width, modeList[vidmode].height );
        } else {
            return va( "%4i x %4i @ %dhz", modeList[vidmode].width, modeList[vidmode].height, modeList[vidmode].displayHz );
        }
    }
    case SYSTEM_FIELD_FRAMERATE:
        return va( "%d FPS", com_engineHz.GetInteger() );
    case SYSTEM_FIELD_VSYNC:
        if ( r_swapInterval.GetInteger() == 1 ) {
            return "#str_swf_smart";
        } else if ( r_swapInterval.GetInteger() == 2 ) {
            return "#str_swf_enabled";
        } else {
            return "#str_swf_disabled";
        }
    case SYSTEM_FIELD_ANTIALIASING:
        if ( r_multiSamples.GetInteger() == 0 ) {
            return "#str_swf_disabled";
        }
        return va( "%dx", r_multiSamples.GetInteger() );
    case SYSTEM_FIELD_MOTIONBLUR:
        if ( r_motionBlur.GetInteger() == 0 ) {
            return "#str_swf_disabled";
        }
        return va( "%dx", idMath::IPow( 2, r_motionBlur.GetInteger() ) );
    case SYSTEM_FIELD_LODBIAS:
        return LinearAdjust( r_lodBias.GetFloat(), -1.0f, 1.0f, 0.0f, 100.0f );
    case SYSTEM_FIELD_BRIGHTNESS:
        return LinearAdjust( r_lightScale.GetFloat(), 2.0f, 4.0f, 0.0f, 100.0f );
    case SYSTEM_FIELD_VOLUME: {
        return 100.0f * Square( 1.0f - ( s_volume_dB.GetFloat() / DB_SILENCE ) );
    }
    }
    return false;
}
Пример #16
0
/*
==============
idUsercmdGenLocal::CmdButtons
==============
*/
void idUsercmdGenLocal::CmdButtons(void)
{
	int		i;

	cmd.buttons = 0;

	// figure button bits
	for (i = 0 ; i <= 7 ; i++) {
		if (ButtonState((usercmdButton_t)(UB_BUTTON0 + i))) {
			cmd.buttons |= 1 << i;
		}
	}

	// check the attack button
	if (ButtonState(UB_ATTACK)) {
		cmd.buttons |= BUTTON_ATTACK;
	}

	// check the run button
	if (toggled_run.on ^(in_alwaysRun.GetBool() && idAsyncNetwork::IsActive())) {
		cmd.buttons |= BUTTON_RUN;
	}

	// check the zoom button
	if (toggled_zoom.on) {
		cmd.buttons |= BUTTON_ZOOM;
	}

	// check the scoreboard button
	if (ButtonState(UB_SHOWSCORES) || ButtonState(UB_IMPULSE19)) {
		// the button is toggled in SP mode as well but without effect
		cmd.buttons |= BUTTON_SCORES;
	}

	// check the mouse look button
	if (ButtonState(UB_MLOOK) ^ in_freeLook.GetInteger()) {
		cmd.buttons |= BUTTON_MLOOK;
	}
}
/*
========================
idSessionLocalWin::Connect_f
========================
*/
void idSessionLocalWin::Connect_f( const idCmdArgs& args )
{
	if( args.Argc() < 2 )
	{
		idLib::Printf( "Usage: Connect to IP.  Use with net_port. \n" );
		return;
	}
	
	Cancel();
	
	if( signInManager->GetMasterLocalUser() == NULL )
	{
		signInManager->RegisterLocalUser( 0 );
	}
	
	lobbyConnectInfo_t connectInfo;
	
	Sys_StringToNetAdr( args.Argv( 1 ), &connectInfo.netAddr, true );
	connectInfo.netAddr.port = net_port.GetInteger();
	
	ConnectAndMoveToLobby( GetPartyLobby(), connectInfo, false );
}
/*
===============
idCommonLocal::SendUsercmd
===============
*/
void idCommonLocal::SendUsercmds( int localClientNum )
{
	if( !mapSpawned )
	{
		return;
	}
	int currentTime = Sys_Milliseconds();
	if( currentTime < nextUsercmdSendTime )
	{
		return;
	}
	idLobbyBase& lobby = session->GetActingGameStateLobbyBase();
	if( lobby.IsHost() )
	{
		return;
	}
	// We always send the last NUM_USERCMD_SEND usercmds
	// Which may result in duplicate usercmds being sent in the case of a low net_ucmdRate
	// But the LZW compressor means the extra usercmds are not large and the redundancy can smooth packet loss
	byte buffer[idPacketProcessor::MAX_FINAL_PACKET_SIZE];
	idBitMsg msg( buffer, sizeof( buffer ) );
	idSerializer ser( msg, true );
	usercmd_t empty;
	usercmd_t* last = &empty;
	
	usercmd_t* cmdBuffer[NUM_USERCMD_SEND];
	const int numCmds = userCmdMgr.GetPlayerCmds( localClientNum, cmdBuffer, NUM_USERCMD_SEND );
	msg.WriteByte( numCmds );
	for( int i = 0; i < numCmds; i++ )
	{
		cmdBuffer[i]->Serialize( ser, *last );
		
		last = cmdBuffer[i];
	}
	session->SendUsercmds( msg );
	
	nextUsercmdSendTime = MSEC_ALIGN_TO_FRAME( currentTime + net_ucmdRate.GetInteger() );
}
Пример #19
0
/*
========================
idLobby::DetectSaturation
See if the ping shot up, which indicates a previously saturated connection
========================
*/
void idLobby::DetectSaturation( int p )
{
	assert( lobbyType == GetActingGameStateLobbyType() );
	
	peer_t& peer = peers[p];
	
	if( !peer.IsConnected() )
	{
		return;
	}
	
	const float pingIncPercentBeforeThottle			= session->GetTitleStorageFloat( "net_pingIncPercentBeforeRecover", net_pingIncPercentBeforeRecover.GetFloat() );
	const int	pingThreshold						= session->GetTitleStorageInt( "net_min_ping_in_ms", net_min_ping_in_ms.GetInteger() );
	const int	maxFailedPingRecoveries				= session->GetTitleStorageInt( "net_maxFailedPingRecoveries", net_maxFailedPingRecoveries.GetInteger() );
	const int	pingRecoveryThrottleTimeInSeconds	= session->GetTitleStorageInt( "net_pingRecoveryThrottleTimeInSeconds", net_pingRecoveryThrottleTimeInSeconds.GetInteger() );
	
	if( peer.lastPingRtt > peer.rightBeforeSnapsPing * pingIncPercentBeforeThottle && peer.lastPingRtt > pingThreshold )
	{
		if( peer.failedPingRecoveries < maxFailedPingRecoveries )
		{
			ThrottleSnapsForXSeconds( p, pingRecoveryThrottleTimeInSeconds, true );
		}
	}
}
Пример #20
0
/*
=============
Sys_Error

Show the early console as an error dialog
=============
*/
void Sys_Error( const char *error, ... ) {
	va_list		argptr;
	char		text[4096];
    MSG        msg;

	va_start( argptr, error );
	vsprintf( text, error, argptr );
	va_end( argptr);

	Conbuf_AppendText( text );
	Conbuf_AppendText( "\n" );

	Win_SetErrorText( text );
	Sys_ShowConsole( 1, true );

	timeEndPeriod( 1 );

	Sys_ShutdownInput();

	GLimp_Shutdown();

	extern idCVar com_productionMode;
	if ( com_productionMode.GetInteger() == 0 ) {
		// wait for the user to quit
		while ( 1 ) {
			if ( !GetMessage( &msg, NULL, 0, 0 ) ) {
				common->Quit();
			}
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
	}
	Sys_DestroyConsole();

	exit (1);
}
Пример #21
0
/*
========================
idResolutionScale::GetConsoleText
========================
*/
void idResolutionScale::GetConsoleText( idStr& s )
{
	float x;
	float y;
	if( rs_enable.GetInteger() == 0 )
	{
		s = "rs-off";
		return;
	}
	GetCurrentResolutionScale( x, y );
	if( rs_display.GetInteger() > 0 )
	{
		x *= 1280.0f;
		y *= 720.0f;
		if( rs_enable.GetInteger() == 1 )
		{
			y = 1.0f;
		}
		else if( rs_enable.GetInteger() == 2 )
		{
			x = 1.0f;
		}
		s = va( "rs-pixels %i", idMath::Ftoi( x * y ) );
	}
	else
	{
		if( rs_enable.GetInteger() == 3 )
		{
			s = va( "%2i%%h,%2i%%v", idMath::Ftoi( 100.0f * x ), idMath::Ftoi( 100.0f * y ) );
		}
		else
		{
			s = va( "%2i%%%s", ( rs_enable.GetInteger() == 1 ) ? idMath::Ftoi( 100.0f * x ) : idMath::Ftoi( 100.0f * y ), ( rs_enable.GetInteger() == 1 ) ? "h" : "v" );
		}
	}
}
Пример #22
0
/*
========================
idSoundHardware_XAudio2::Update
========================
*/
void idSoundHardware_XAudio2::Update()
{
	if( pXAudio2 == NULL )
	{
		int nowTime = Sys_Milliseconds();
		if( lastResetTime + 1000 < nowTime )
		{
			lastResetTime = nowTime;
			Init();
		}
		return;
	}
	if( soundSystem->IsMuted() )
	{
		pMasterVoice->SetVolume( 0.0f, OPERATION_SET );
	}
	else
	{
		pMasterVoice->SetVolume( DBtoLinear( s_volume_dB.GetFloat() ), OPERATION_SET );
	}
	
	pXAudio2->CommitChanges( XAUDIO2_COMMIT_ALL );
	
	// IXAudio2SourceVoice::Stop() has been called for every sound on the
	// zombie list, but it is documented as asyncronous, so we have to wait
	// until it actually reports that it is no longer playing.
	for( int i = 0; i < zombieVoices.Num(); i++ )
	{
		zombieVoices[i]->FlushSourceBuffers();
		if( !zombieVoices[i]->IsPlaying() )
		{
			freeVoices.Append( zombieVoices[i] );
			zombieVoices.RemoveIndexFast( i );
			i--;
		}
		else
		{
			static int playingZombies;
			playingZombies++;
		}
	}
	
	if( s_showPerfData.GetBool() )
	{
		XAUDIO2_PERFORMANCE_DATA perfData;
		pXAudio2->GetPerformanceData( &perfData );
		idLib::Printf( "Voices: %d/%d CPU: %.2f%% Mem: %dkb\n", perfData.ActiveSourceVoiceCount, perfData.TotalSourceVoiceCount, perfData.AudioCyclesSinceLastQuery / ( float )perfData.TotalCyclesSinceLastQuery, perfData.MemoryUsageInBytes / 1024 );
	}
	
	if( vuMeterRMS == NULL )
	{
		// Init probably hasn't been called yet
		return;
	}
	
	vuMeterRMS->Enable( s_showLevelMeter.GetBool() );
	vuMeterPeak->Enable( s_showLevelMeter.GetBool() );
	
	if( !s_showLevelMeter.GetBool() )
	{
		pMasterVoice->DisableEffect( 0 );
		return;
	}
	else
	{
		pMasterVoice->EnableEffect( 0 );
	}
	
	float peakLevels[ 8 ];
	float rmsLevels[ 8 ];
	
	XAUDIO2FX_VOLUMEMETER_LEVELS levels;
	levels.ChannelCount = outputChannels;
	levels.pPeakLevels = peakLevels;
	levels.pRMSLevels = rmsLevels;
	
	if( levels.ChannelCount > 8 )
	{
		levels.ChannelCount = 8;
	}
	
	pMasterVoice->GetEffectParameters( 0, &levels, sizeof( levels ) );
	
	int currentTime = Sys_Milliseconds();
	for( int i = 0; i < outputChannels; i++ )
	{
		if( vuMeterPeakTimes[i] < currentTime )
		{
			vuMeterPeak->SetValue( i, vuMeterPeak->GetValue( i ) * 0.9f, colorRed );
		}
	}
	
	float width = 20.0f;
	float height = 200.0f;
	float left = 100.0f;
	float top = 100.0f;
	
	sscanf( s_meterPosition.GetString(), "%f %f %f %f", &left, &top, &width, &height );
	
	vuMeterRMS->SetPosition( left, top, width * levels.ChannelCount, height );
	vuMeterPeak->SetPosition( left, top, width * levels.ChannelCount, height );
	
	for( uint32 i = 0; i < levels.ChannelCount; i++ )
	{
		vuMeterRMS->SetValue( i, rmsLevels[ i ], idVec4( 0.5f, 1.0f, 0.0f, 1.00f ) );
		if( peakLevels[ i ] >= vuMeterPeak->GetValue( i ) )
		{
			vuMeterPeak->SetValue( i, peakLevels[ i ], colorRed );
			vuMeterPeakTimes[i] = currentTime + s_meterTopTime.GetInteger();
		}
	}
}
Пример #23
0
/*
========================
idSoundHardware_XAudio2::Init
========================
*/
void idSoundHardware_XAudio2::Init()
{

	cmdSystem->AddCommand( "listDevices", listDevices_f, 0, "Lists the connected sound devices", NULL );
	
	DWORD xAudioCreateFlags = 0;
	
// RB: not available on Windows 8 SDK
#if !defined(USE_WINRT) && defined(_DEBUG) // (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) && defined(_DEBUG)
	xAudioCreateFlags |= XAUDIO2_DEBUG_ENGINE;
#endif
// RB end

	XAUDIO2_PROCESSOR xAudioProcessor = XAUDIO2_DEFAULT_PROCESSOR;
	
// RB: not available on Windows 8 SDK
	if( FAILED( XAudio2Create( &pXAudio2, xAudioCreateFlags, xAudioProcessor ) ) )
	{
#if !defined(USE_WINRT) && defined(_DEBUG) // (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) && defined(_DEBUG)
		if( xAudioCreateFlags & XAUDIO2_DEBUG_ENGINE )
		{
			// in case the debug engine isn't installed
			xAudioCreateFlags &= ~XAUDIO2_DEBUG_ENGINE;
			if( FAILED( XAudio2Create( &pXAudio2, xAudioCreateFlags, xAudioProcessor ) ) )
			{
				idLib::FatalError( "Failed to create XAudio2 engine.  Try installing the latest DirectX." );
				return;
			}
		}
		else
#endif
// RB end
		{
			idLib::FatalError( "Failed to create XAudio2 engine.  Try installing the latest DirectX." );
			return;
		}
	}
#ifdef _DEBUG
	XAUDIO2_DEBUG_CONFIGURATION debugConfiguration = { 0 };
	debugConfiguration.TraceMask = XAUDIO2_LOG_WARNINGS;
	debugConfiguration.BreakMask = XAUDIO2_LOG_ERRORS;
	pXAudio2->SetDebugConfiguration( &debugConfiguration );
#endif
	
	// Register the sound engine callback
	pXAudio2->RegisterForCallbacks( &soundEngineCallback );
	soundEngineCallback.hardware = this;
	UINT32 deviceCount = 0;
	DWORD outputSampleRate = 44100; // Max( (DWORD)XAUDIO2FX_REVERB_MIN_FRAMERATE, Min( (DWORD)XAUDIO2FX_REVERB_MAX_FRAMERATE, deviceDetails.OutputFormat.Format.nSamplesPerSec ) );
	
	// RB: not available on Windows 8 SDK
#if defined(USE_WINRT) //(_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)
	
	IMMDeviceEnumerator*     immDevEnum       = nullptr;
	IMMDeviceCollection*     immDevCollection = nullptr;
	IMMDevice*               immDev           = nullptr;
	std::vector<AudioDevice> vAudioDevices;
	
	HRESULT hResult = CoCreateInstance(
						  __uuidof( MMDeviceEnumerator ), NULL,
						  CLSCTX_ALL, __uuidof( IMMDeviceEnumerator ), ( void** ) &immDevEnum );
						  
	if( FAILED( hResult ) )
	{
		idLib::Warning( "Failed to get audio enumerator" );
		pXAudio2->Release();
		pXAudio2 = NULL;
		return;
	}
	
	hResult = immDevEnum->EnumAudioEndpoints( eRender, DEVICE_STATE_ACTIVE, &immDevCollection );
	if( FAILED( hResult ) )
	{
		idLib::Warning( "Failed to get audio endpoints" );
		pXAudio2->Release();
		pXAudio2 = NULL;
		return;
	}
	
	hResult = immDevCollection->GetCount( &deviceCount );
	if( FAILED( hResult ) )
	{
		idLib::Warning( "No audio devices found" );
		pXAudio2->Release();
		pXAudio2 = NULL;
		return;
	}
	
	for( UINT i = 0; i < deviceCount; i++ )
	{
		IPropertyStore* propStore = nullptr;
		PROPVARIANT     varName;
		PROPVARIANT     varId;
		
		PropVariantInit( &varId );
		PropVariantInit( &varName );
		
		hResult = immDevCollection->Item( i, &immDev );
		if( SUCCEEDED( hResult ) )
		{
			hResult = immDev->OpenPropertyStore( STGM_READ, &propStore );
		}
		if( SUCCEEDED( hResult ) )
		{
			hResult = propStore->GetValue( PKEY_AudioEndpoint_Path, &varId );
		}
		
		if( SUCCEEDED( hResult ) )
		{
			hResult = propStore->GetValue( PKEY_Device_FriendlyName, &varName );
		}
		
		if( SUCCEEDED( hResult ) )
		{
			assert( varId.vt == VT_LPWSTR );
			assert( varName.vt == VT_LPWSTR );
			
			// Now save somewhere the device display name & id
			AudioDevice ad;
			ad.name = varName.pwszVal;
			ad.id   = varId.pwszVal;
			
			vAudioDevices.push_back( ad );
		}
		
		PropVariantClear( &varName );
		PropVariantClear( &varId );
		
		if( propStore != nullptr )
		{
			propStore->Release();
		}
		
		if( immDev != nullptr )
		{
			immDev->Release();
		}
	}
	
	
	immDevCollection->Release();
	immDevEnum->Release();
	
	int preferredDevice = s_device.GetInteger();
	if( !vAudioDevices.empty() )
	{
		if( SUCCEEDED( pXAudio2->CreateMasteringVoice( &pMasterVoice,
					   XAUDIO2_DEFAULT_CHANNELS,
					   outputSampleRate,
					   0,
					   vAudioDevices.at( 0 ).id.c_str(),
					   NULL,
					   AudioCategory_GameEffects ) ) )
		{
			XAUDIO2_VOICE_DETAILS deviceDetails;
			pMasterVoice->GetVoiceDetails( &deviceDetails );
			
			pMasterVoice->SetVolume( DBtoLinear( s_volume_dB.GetFloat() ) );
			
			outputChannels = deviceDetails.InputChannels;
			DWORD win8_channelMask;
			pMasterVoice->GetChannelMask( &win8_channelMask );
			
			channelMask = ( unsigned int )win8_channelMask;
			idLib::Printf( "Using device %s\n", vAudioDevices.at( 0 ).name );
		}
		else
		{
			idLib::Warning( "Failed to create master voice" );
			pXAudio2->Release();
			pXAudio2 = NULL;
			return;
		}
	}
	
#else
	if( pXAudio2->GetDeviceCount( &deviceCount ) != S_OK || deviceCount == 0 )
	{
		idLib::Warning( "No audio devices found" );
		pXAudio2->Release();
		pXAudio2 = NULL;
		return;
	}
	
	idCmdArgs args;
	listDevices_f( args );
	
	int preferredDevice = s_device.GetInteger();
	if( preferredDevice < 0 || preferredDevice >= ( int )deviceCount )
	{
		int preferredChannels = 0;
		for( unsigned int i = 0; i < deviceCount; i++ )
		{
			XAUDIO2_DEVICE_DETAILS deviceDetails;
			if( pXAudio2->GetDeviceDetails( i, &deviceDetails ) != S_OK )
			{
				continue;
			}
	
			if( deviceDetails.Role & DefaultGameDevice )
			{
				// if we find a device the user marked as their preferred 'game' device, then always use that
				preferredDevice = i;
				preferredChannels = deviceDetails.OutputFormat.Format.nChannels;
				break;
			}
	
			if( deviceDetails.OutputFormat.Format.nChannels > preferredChannels )
			{
				preferredDevice = i;
				preferredChannels = deviceDetails.OutputFormat.Format.nChannels;
			}
		}
	}
	
	idLib::Printf( "Using device %d\n", preferredDevice );
	
	XAUDIO2_DEVICE_DETAILS deviceDetails;
	if( pXAudio2->GetDeviceDetails( preferredDevice, &deviceDetails ) != S_OK )
	{
		// One way this could happen is if a device is removed between the loop and this line of code
		// Highly unlikely but possible
		idLib::Warning( "Failed to get device details" );
		pXAudio2->Release();
		pXAudio2 = NULL;
		return;
	}
	
	
	if( FAILED( pXAudio2->CreateMasteringVoice( &pMasterVoice, XAUDIO2_DEFAULT_CHANNELS, outputSampleRate, 0, preferredDevice, NULL ) ) )
	{
		idLib::Warning( "Failed to create master voice" );
		pXAudio2->Release();
		pXAudio2 = NULL;
		return;
	}
	pMasterVoice->SetVolume( DBtoLinear( s_volume_dB.GetFloat() ) );
	
	outputChannels = deviceDetails.OutputFormat.Format.nChannels;
	channelMask = deviceDetails.OutputFormat.dwChannelMask;
	
#endif // #if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/)
	
	idSoundVoice::InitSurround( outputChannels, channelMask );
	
	// ---------------------
	// Create VU Meter Effect
	// ---------------------
	IUnknown* vuMeter = NULL;
	XAudio2CreateVolumeMeter( &vuMeter, 0 );
	
	XAUDIO2_EFFECT_DESCRIPTOR descriptor;
	descriptor.InitialState = true;
	descriptor.OutputChannels = outputChannels;
	descriptor.pEffect = vuMeter;
	
	XAUDIO2_EFFECT_CHAIN chain;
	chain.EffectCount = 1;
	chain.pEffectDescriptors = &descriptor;
	
	pMasterVoice->SetEffectChain( &chain );
	
	vuMeter->Release();
	
	// ---------------------
	// Create VU Meter Graph
	// ---------------------
	
	vuMeterRMS = console->CreateGraph( outputChannels );
	vuMeterPeak = console->CreateGraph( outputChannels );
	// DG: make sure they're not NULL (as it's currently the case with the cegui-based console)
	if( vuMeterRMS && vuMeterPeak )
	{
		vuMeterRMS->Enable( false );
		vuMeterPeak->Enable( false );
		
		memset( vuMeterPeakTimes, 0, sizeof( vuMeterPeakTimes ) );
		
		vuMeterPeak->SetFillMode( idDebugGraph::GRAPH_LINE );
		vuMeterPeak->SetBackgroundColor( idVec4( 0.0f, 0.0f, 0.0f, 0.0f ) );
		
		vuMeterRMS->AddGridLine( 0.500f, idVec4( 0.5f, 0.5f, 0.5f, 1.0f ) );
		vuMeterRMS->AddGridLine( 0.250f, idVec4( 0.5f, 0.5f, 0.5f, 1.0f ) );
		vuMeterRMS->AddGridLine( 0.125f, idVec4( 0.5f, 0.5f, 0.5f, 1.0f ) );
		
		const char* channelNames[] = { "L", "R", "C", "S", "Lb", "Rb", "Lf", "Rf", "Cb", "Ls", "Rs" };
		for( int i = 0, ci = 0; ci < sizeof( channelNames ) / sizeof( channelNames[0] ); ci++ )
		{
			if( ( channelMask & BIT( ci ) ) == 0 )
			{
				continue;
			}
			vuMeterRMS->SetLabel( i, channelNames[ci] );
			i++;
		}
	}
	
	// ---------------------
	// Create submix buffer
	// ---------------------
	if( FAILED( pXAudio2->CreateSubmixVoice( &pSubmixVoice, 1, outputSampleRate, 0, 0, NULL, NULL ) ) )
	{
		idLib::FatalError( "Failed to create submix voice" );
	}
	
	// XAudio doesn't really impose a maximum number of voices
	voices.SetNum( voices.Max() );
	freeVoices.SetNum( voices.Max() );
	zombieVoices.SetNum( 0 );
	for( int i = 0; i < voices.Num(); i++ )
	{
		freeVoices[i] = &voices[i];
	}
// RB end
}
Пример #24
0
/*
================
idServerScan::IsFiltered
================
*/
bool idServerScan::IsFiltered( const networkServer_t server )
{
	int					i;
	const idKeyValue	*keyval;
	
	// OS support filter
#if 0
	// filter out pure servers that won't provide checksumed game code for client OS
	keyval = server.serverInfo.FindKey( "si_pure" );
	
	if( keyval && !idStr::Cmp( keyval->GetValue(), "1" ) )
	{
		if( ( server.OSMask & ( 1 << BUILD_OS_ID ) ) == 0 )
		{
			return true;
		}
	}
	
#else	
	if( ( server.OSMask & ( 1 << BUILD_OS_ID ) ) == 0 )
	{
		return true;
	}	
#endif
	// password filter
	keyval = server.serverInfo.FindKey( "si_usePass" );
	
	if( keyval && gui_filter_password.GetInteger() == 1 )
	{
		// show passworded only
		if( keyval->GetValue() [0] == '0' )
		{
			return true;
		}
	}
	else if( keyval && gui_filter_password.GetInteger() == 2 )
	{
		// show no password only
		if( keyval->GetValue() [0] != '0' )
		{
			return true;
		}
	}
	
	// players filter
	keyval = server.serverInfo.FindKey( "si_maxPlayers" );
	
	if( keyval )
	{
		if( gui_filter_players.GetInteger() == 1 && server.clients == atoi( keyval->GetValue() ) )
		{
			return true;
		}
		else if( gui_filter_players.GetInteger() == 2 && ( !server.clients || server.clients == atoi( keyval->GetValue() ) ) )
		{
			return true;
		}
	}
	
	// gametype filter
	keyval = server.serverInfo.FindKey( "si_gameType" );
	
	if( keyval && gui_filter_gameType.GetInteger() )
	{
		i = 0;
		
		while( l_gameTypes[i] )
		{
			if( !keyval->GetValue().Icmp( l_gameTypes[i] ) )
			{
				break;
			}
			
			i++;
		}
		
		if( l_gameTypes[i] && i != gui_filter_gameType.GetInteger() - 1 )
		{
			return true;
		}
	}
	
	// idle server filter
	keyval = server.serverInfo.FindKey( "si_idleServer" );
	
	if( keyval && !gui_filter_idle.GetInteger() )
	{
		if( !keyval->GetValue().Icmp( "1" ) )
		{
			return true;
		}
	}
	
	// autofilter D3XP games if the user does not has the XP installed
	if( !fileSystem->HasD3XP() && !idStr::Icmp( server.serverInfo.GetString( "fs_game" ), "d3xp" ) )
	{
		return true;
	}
	
	// filter based on the game doom or XP
	if( gui_filter_game.GetInteger() == 1 )  //Only Doom
	{
		if( idStr::Icmp( server.serverInfo.GetString( "fs_game" ), "" ) )
		{
			return true;
		}
	}
	else if( gui_filter_game.GetInteger() == 2 )    //Only D3XP
	{
		if( idStr::Icmp( server.serverInfo.GetString( "fs_game" ), "d3xp" ) )
		{
			return true;
		}
	}
	
	return false;
}
/*
========================
idLobby::PickNewHostInternal
========================
*/
void idLobby::PickNewHostInternal( bool forceMe, bool inviteOldHost )
{

	if( migrationInfo.state == MIGRATE_PICKING_HOST )
	{
		return;		// Already picking new host
	}
	
	idLib::Printf( "PickNewHost: Started picking new host %s.\n", GetLobbyName() );
	
	if( IsHost() )
	{
		idLib::Printf( "PickNewHost: Already host of session %s\n", GetLobbyName() );
		return;
	}
	
	// Find the user with the lowest ping
	int bestUserIndex			= -1;
	int bestPingMs				= 0;
	lobbyUserID_t bestUserId;
	
	for( int i = 0; i < GetNumLobbyUsers(); i++ )
	{
		lobbyUser_t* user = GetLobbyUser( i );
		
		if( !verify( user != NULL ) )
		{
			continue;
		}
		
		if( user->IsDisconnected() )
		{
			continue;
		}
		
		if( user->peerIndex == -1 )
		{
			continue;		// Don't try and pick old host
		}
		
		if( bestUserIndex == -1 || IsBetterHost( user->pingMs, user->lobbyUserID, bestPingMs, bestUserId ) )
		{
			bestUserIndex	= i;
			bestPingMs		= user->pingMs;
			bestUserId		= user->lobbyUserID;
		}
		
		if( user->peerIndex == net_migration_forcePeerAsHost.GetInteger() )
		{
			bestUserIndex	= i;
			bestPingMs		= user->pingMs;
			bestUserId		= user->lobbyUserID;
			break;
		}
	}
	
	// Remember when we first started picking a new host
	migrationInfo.state						= MIGRATE_PICKING_HOST;
	migrationInfo.migrationStartTime		= Sys_Milliseconds();
	
	migrationInfo.persistUntilGameEndsData.wasMigratedGame = sessionCB->GetState() == idSession::INGAME;
	
	if( bestUserIndex == -1 )  	// This can happen if we call PickNewHost on an lobby that was Shutdown
	{
		NET_VERBOSE_PRINT( "MIGRATION: PickNewHost was called on an lobby that was Shutdown\n" );
		BecomeHost();
		return;
	}
	
	NET_VERBOSE_PRINT( "MIGRATION: Chose user index %d (%s) for new host\n", bestUserIndex, GetLobbyUser( bestUserIndex )->gamertag );
	
	bool bestWasLocal = IsSessionUserIndexLocal( bestUserIndex );		// Check before shutting down the lobby
	migrateMsgFlags = parms.matchFlags;						// Save off match parms
	
	// Build invite list
	BuildMigrationInviteList( inviteOldHost );
	
	// If the best user is on this machine, then we become the host now, otherwise, wait for a new host to contact us
	if( forceMe || bestWasLocal )
	{
		BecomeHost();
	}
}
Пример #26
0
/*
========================
NET_OpenSocks
========================
*/
void NET_OpenSocks( int port )
{
	sockaddr_in			address;
	struct hostent*		h;
	int					len;
	bool				rfc1929;
	unsigned char		buf[64];
	
	usingSocks = false;
	
	idLib::Printf( "Opening connection to SOCKS server.\n" );
	
	if( ( socks_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET )
	{
		idLib::Printf( "WARNING: NET_OpenSocks: socket: %s\n", NET_ErrorString() );
		return;
	}
	
	h = gethostbyname( net_socksServer.GetString() );
	if( h == NULL )
	{
		idLib::Printf( "WARNING: NET_OpenSocks: gethostbyname: %s\n", NET_ErrorString() );
		return;
	}
	if( h->h_addrtype != AF_INET )
	{
		idLib::Printf( "WARNING: NET_OpenSocks: gethostbyname: address type was not AF_INET\n" );
		return;
	}
	address.sin_family = AF_INET;
	address.sin_addr.s_addr = *( in_addr_t* )h->h_addr_list[0];
	address.sin_port = htons( ( short )net_socksPort.GetInteger() );
	
	if( connect( socks_socket, ( sockaddr* )&address, sizeof( address ) ) == SOCKET_ERROR )
	{
		idLib::Printf( "NET_OpenSocks: connect: %s\n", NET_ErrorString() );
		return;
	}
	
	// send socks authentication handshake
	if( *net_socksUsername.GetString() || *net_socksPassword.GetString() )
	{
		rfc1929 = true;
	}
	else
	{
		rfc1929 = false;
	}
	
	buf[0] = 5;		// SOCKS version
	// method count
	if( rfc1929 )
	{
		buf[1] = 2;
		len = 4;
	}
	else
	{
		buf[1] = 1;
		len = 3;
	}
	buf[2] = 0;		// method #1 - method id #00: no authentication
	if( rfc1929 )
	{
		buf[2] = 2;		// method #2 - method id #02: username/password
	}
	if( send( socks_socket, ( const char* )buf, len, 0 ) == SOCKET_ERROR )
	{
		idLib::Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
		return;
	}
	
	// get the response
	len = recv( socks_socket, ( char* )buf, 64, 0 );
	if( len == SOCKET_ERROR )
	{
		idLib::Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
		return;
	}
	if( len != 2 || buf[0] != 5 )
	{
		idLib::Printf( "NET_OpenSocks: bad response\n" );
		return;
	}
	switch( buf[1] )
	{
		case 0:	// no authentication
			break;
		case 2: // username/password authentication
			break;
		default:
			idLib::Printf( "NET_OpenSocks: request denied\n" );
			return;
	}
	
	// do username/password authentication if needed
	if( buf[1] == 2 )
	{
		int		ulen;
		int		plen;
		
		// build the request
		ulen = idStr::Length( net_socksUsername.GetString() );
		plen = idStr::Length( net_socksPassword.GetString() );
		
		buf[0] = 1;		// username/password authentication version
		buf[1] = ulen;
		if( ulen )
		{
			memcpy( &buf[2], net_socksUsername.GetString(), ulen );
		}
		buf[2 + ulen] = plen;
		if( plen )
		{
			memcpy( &buf[3 + ulen], net_socksPassword.GetString(), plen );
		}
		
		// send it
		if( send( socks_socket, ( const char* )buf, 3 + ulen + plen, 0 ) == SOCKET_ERROR )
		{
			idLib::Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
			return;
		}
		
		// get the response
		len = recv( socks_socket, ( char* )buf, 64, 0 );
		if( len == SOCKET_ERROR )
		{
			idLib::Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
			return;
		}
		if( len != 2 || buf[0] != 1 )
		{
			idLib::Printf( "NET_OpenSocks: bad response\n" );
			return;
		}
		if( buf[1] != 0 )
		{
			idLib::Printf( "NET_OpenSocks: authentication failed\n" );
			return;
		}
	}
	
	// send the UDP associate request
	buf[0] = 5;		// SOCKS version
	buf[1] = 3;		// command: UDP associate
	buf[2] = 0;		// reserved
	buf[3] = 1;		// address type: IPV4
	*( int* )&buf[4] = INADDR_ANY;
	*( short* )&buf[8] = htons( ( short )port );		// port
	if( send( socks_socket, ( const char* )buf, 10, 0 ) == SOCKET_ERROR )
	{
		idLib::Printf( "NET_OpenSocks: send: %s\n", NET_ErrorString() );
		return;
	}
	
	// get the response
	len = recv( socks_socket, ( char* )buf, 64, 0 );
	if( len == SOCKET_ERROR )
	{
		idLib::Printf( "NET_OpenSocks: recv: %s\n", NET_ErrorString() );
		return;
	}
	if( len < 2 || buf[0] != 5 )
	{
		idLib::Printf( "NET_OpenSocks: bad response\n" );
		return;
	}
	// check completion code
	if( buf[1] != 0 )
	{
		idLib::Printf( "NET_OpenSocks: request denied: %i\n", buf[1] );
		return;
	}
	if( buf[3] != 1 )
	{
		idLib::Printf( "NET_OpenSocks: relay address is not IPV4: %i\n", buf[3] );
		return;
	}
	socksRelayAddr.sin_family = AF_INET;
	socksRelayAddr.sin_addr.s_addr = *( int* )&buf[4];
	socksRelayAddr.sin_port = *( short* )&buf[8];
	memset( socksRelayAddr.sin_zero, 0, sizeof( socksRelayAddr.sin_zero ) );
	
	usingSocks = true;
}
Пример #27
0
/*
========================
idMenuScreen_Shell_Root::ShowScreen
========================
*/
void idMenuScreen_Shell_Root::ShowScreen( const mainMenuTransition_t transitionType ) {

	if ( menuData != NULL && menuData->GetPlatform() != 2 ) {
		idList< idList< idStr, TAG_IDLIB_LIST_MENU >, TAG_IDLIB_LIST_MENU > menuOptions;	
		idList< idStr > option;

		int index = 0;

		if ( g_demoMode.GetBool() ) {
			idMenuWidget_Button * buttonWidget = NULL;

			option.Append( "START DEMO" );	// START DEMO
			menuOptions.Append( option );
			options->GetChildByIndex( index ).ClearEventActions();
			options->GetChildByIndex( index ).AddEventAction( WIDGET_EVENT_PRESS ).Set( WIDGET_ACTION_COMMAND, ROOT_CMD_START_DEMO );
			buttonWidget = dynamic_cast< idMenuWidget_Button * >( &options->GetChildByIndex( index ) );
			if ( buttonWidget != NULL ) {
				buttonWidget->SetDescription( "Launch the demo" );
			}
			index++;

			if ( g_demoMode.GetInteger() == 2 ) {
				option.Clear();
				option.Append( "START PRESS DEMO" );	// START DEMO
				menuOptions.Append( option );
				options->GetChildByIndex( index ).ClearEventActions();
				options->GetChildByIndex( index ).AddEventAction( WIDGET_EVENT_PRESS ).Set( WIDGET_ACTION_COMMAND, ROOT_CMD_START_DEMO2 );
				buttonWidget = dynamic_cast< idMenuWidget_Button * >( &options->GetChildByIndex( index ) );
				if ( buttonWidget != NULL ) {
					buttonWidget->SetDescription( "Launch the press demo" );
				}
				index++;
			}

			option.Clear();
			option.Append( "#str_swf_settings" );	// settings
			menuOptions.Append( option );
			options->GetChildByIndex( index ).ClearEventActions();
			options->GetChildByIndex( index ).AddEventAction( WIDGET_EVENT_PRESS ).Set( WIDGET_ACTION_COMMAND, ROOT_CMD_SETTINGS );
			buttonWidget = dynamic_cast< idMenuWidget_Button * >( &options->GetChildByIndex( index ) );
			if ( buttonWidget != NULL ) {
				buttonWidget->SetDescription( "#str_02206" );
			}
			index++;

			option.Clear();
			option.Append( "#str_swf_quit" );	// quit
			menuOptions.Append( option );
			options->GetChildByIndex( index ).ClearEventActions();
			options->GetChildByIndex( index ).AddEventAction( WIDGET_EVENT_PRESS ).Set( WIDGET_ACTION_COMMAND, ROOT_CMD_QUIT );
			buttonWidget = dynamic_cast< idMenuWidget_Button * >( &options->GetChildByIndex( index ) );
			if ( buttonWidget != NULL ) {
				buttonWidget->SetDescription( "#str_01976" );
			}
			index++;

		} else {

			idMenuWidget_Button * buttonWidget = NULL;

#if !defined ( ID_RETAIL ) 
			option.Append( "DEV" );	// DEV
			menuOptions.Append( option );
			options->GetChildByIndex( index ).ClearEventActions();
			options->GetChildByIndex( index ).AddEventAction( WIDGET_EVENT_PRESS ).Set( WIDGET_ACTION_COMMAND, ROOT_CMD_DEV );
			buttonWidget = dynamic_cast< idMenuWidget_Button * >( &options->GetChildByIndex( index ) );
			if ( buttonWidget != NULL ) {
				buttonWidget->SetDescription( "View a list of maps available for play" );
			}
			index++;
#endif
			
			option.Clear();
			option.Append( "#str_swf_campaign" );	// singleplayer
			menuOptions.Append( option );
			options->GetChildByIndex( index ).ClearEventActions();
			options->GetChildByIndex( index ).AddEventAction( WIDGET_EVENT_PRESS ).Set( WIDGET_ACTION_COMMAND, ROOT_CMD_CAMPAIGN );
			buttonWidget = dynamic_cast< idMenuWidget_Button * >( &options->GetChildByIndex( index ) );
			if ( buttonWidget != NULL ) {
				buttonWidget->SetDescription( "#str_swf_campaign_desc" );
			}
			index++;
			
			option.Clear();
			option.Append( "#str_swf_multiplayer" );	// multiplayer
			menuOptions.Append( option );
			options->GetChildByIndex( index ).ClearEventActions();
			options->GetChildByIndex( index ).AddEventAction( WIDGET_EVENT_PRESS ).Set( WIDGET_ACTION_COMMAND, ROOT_CMD_MULTIPLAYER );
			buttonWidget = dynamic_cast< idMenuWidget_Button * >( &options->GetChildByIndex( index ) );
			if ( buttonWidget != NULL ) {
				buttonWidget->SetDescription( "#str_02215" );
			}
			index++;
			
			option.Clear();
			option.Append( "#str_swf_settings" );	// settings
			menuOptions.Append( option );
			options->GetChildByIndex( index ).ClearEventActions();
			options->GetChildByIndex( index ).AddEventAction( WIDGET_EVENT_PRESS ).Set( WIDGET_ACTION_COMMAND, ROOT_CMD_SETTINGS );
			buttonWidget = dynamic_cast< idMenuWidget_Button * >( &options->GetChildByIndex( index ) );
			if ( buttonWidget != NULL ) {
				buttonWidget->SetDescription( "#str_02206" );
			}
			index++;
			

			option.Clear();
			option.Append( "#str_swf_credits" );	// credits
			menuOptions.Append( option );
			options->GetChildByIndex( index ).ClearEventActions();
			options->GetChildByIndex( index ).AddEventAction( WIDGET_EVENT_PRESS ).Set( WIDGET_ACTION_COMMAND, ROOT_CMD_CREDITS );
			buttonWidget = dynamic_cast< idMenuWidget_Button * >( &options->GetChildByIndex( index ) );
			if ( buttonWidget != NULL ) {
				buttonWidget->SetDescription( "#str_02219" );
			}
			index++;

			// only add quit option for PC
			option.Clear();
			option.Append( "#str_swf_quit" );	// quit
			menuOptions.Append( option );
			options->GetChildByIndex( index ).ClearEventActions();
			options->GetChildByIndex( index ).AddEventAction( WIDGET_EVENT_PRESS ).Set( WIDGET_ACTION_COMMAND, ROOT_CMD_QUIT );
			buttonWidget = dynamic_cast< idMenuWidget_Button * >( &options->GetChildByIndex( index ) );
			if ( buttonWidget != NULL ) {
				buttonWidget->SetDescription( "#str_01976" );
			}
			index++;
		}
		options->SetListData( menuOptions );
	} else {
		idList< idList< idStr, TAG_IDLIB_LIST_MENU >, TAG_IDLIB_LIST_MENU > menuOptions;
		options->SetListData( menuOptions );
	}

	idMenuScreen::ShowScreen( transitionType );

	if ( menuData != NULL && menuData->GetPlatform() == 2 ) {
		idMenuHandler_Shell * shell = dynamic_cast< idMenuHandler_Shell * >( menuData );
		if ( shell != NULL ) {
			idMenuWidget_MenuBar * menuBar = shell->GetMenuBar();
			if ( menuBar != NULL ) {
				menuBar->SetFocusIndex( GetRootIndex() );
			}
		}
	}
}
Пример #28
0
/*
=================
idUsercmdGenLocal::MouseMove
=================
*/
void idUsercmdGenLocal::MouseMove( void ) {
	float		mx, my, strafeMx, strafeMy;
	static int	history[8][2];
	static int	historyCounter;
	int			i;

	history[historyCounter&7][0] = mouseDx;
	history[historyCounter&7][1] = mouseDy;
	
	// allow mouse movement to be smoothed together
	int smooth = m_smooth.GetInteger();
	if ( smooth < 1 ) {
		smooth = 1;
	}
	if ( smooth > 8 ) {
		smooth = 8;
	}
	mx = 0;
	my = 0;
	for ( i = 0 ; i < smooth ; i++ ) {
		mx += history[ ( historyCounter - i + 8 ) & 7 ][0];
		my += history[ ( historyCounter - i + 8 ) & 7 ][1];
	}
	mx /= smooth;
	my /= smooth;

	// use a larger smoothing for strafing
	smooth = m_strafeSmooth.GetInteger();
	if ( smooth < 1 ) {
		smooth = 1;
	}
	if ( smooth > 8 ) {
		smooth = 8;
	}
	strafeMx = 0;
	strafeMy = 0;
	for ( i = 0 ; i < smooth ; i++ ) {
		strafeMx += history[ ( historyCounter - i + 8 ) & 7 ][0];
		strafeMy += history[ ( historyCounter - i + 8 ) & 7 ][1];
	}
	strafeMx /= smooth;
	strafeMy /= smooth;

	historyCounter++;

	if ( idMath::Fabs( mx ) > 1000 || idMath::Fabs( my ) > 1000 ) {
		Sys_DebugPrintf( "idUsercmdGenLocal::MouseMove: Ignoring ridiculous mouse delta.\n" );
		mx = my = 0;
	}

	mx *= sensitivity.GetFloat();
	my *= sensitivity.GetFloat();

	if ( m_showMouseRate.GetBool() ) {
		Sys_DebugPrintf( "[%3i %3i  = %5.1f %5.1f = %5.1f %5.1f] ", mouseDx, mouseDy, mx, my, strafeMx, strafeMy );
	}

	mouseDx = 0;
	mouseDy = 0;

	if ( !strafeMx && !strafeMy ) {
		return;
	}

	if ( ButtonState( UB_STRAFE ) || !( cmd.buttons & BUTTON_MLOOK ) ) {
		// add mouse X/Y movement to cmd
		strafeMx *= m_strafeScale.GetFloat();
		strafeMy *= m_strafeScale.GetFloat();
		// clamp as a vector, instead of separate floats
		float len = sqrt( strafeMx * strafeMx + strafeMy * strafeMy );
		if ( len > 127 ) {
			strafeMx = strafeMx * 127 / len;
			strafeMy = strafeMy * 127 / len;
		}
	}

	if ( !ButtonState( UB_STRAFE ) ) {
		viewangles[YAW] -= m_yaw.GetFloat() * mx;
	} else {
		cmd.rightmove = idMath::ClampChar( (int)(cmd.rightmove + strafeMx) );
	}

	if ( !ButtonState( UB_STRAFE ) && ( cmd.buttons & BUTTON_MLOOK ) ) {
		viewangles[PITCH] += m_pitch.GetFloat() * my;
	} else {
		cmd.forwardmove = idMath::ClampChar( (int)(cmd.forwardmove - strafeMy) );
	}
}
/*
========================
idMenuScreen_Shell_PartyLobby::HandleAction h
========================
*/
bool idMenuScreen_Shell_PartyLobby::HandleAction( idWidgetAction& action, const idWidgetEvent& event, idMenuWidget* widget, bool forceHandled )
{

	if( menuData == NULL )
	{
		return true;
	}
	
	if( menuData->ActiveScreen() != SHELL_AREA_PARTY_LOBBY )
	{
		return false;
	}
	
	widgetAction_t actionType = action.GetType();
	const idSWFParmList& parms = action.GetParms();
	
	switch( actionType )
	{
		case WIDGET_ACTION_JOY4_ON_PRESS:
		{
		
			idLobbyBase& activeLobby = session->GetPartyLobbyBase();
			lobbyUserID_t luid;
			if( CanKickSelectedPlayer( luid ) )
			{
				activeLobby.KickLobbyUser( luid );
			}
			return true;
		}
		case WIDGET_ACTION_GO_BACK:
		{
			class idSWFScriptFunction_Accept : public idSWFScriptFunction_RefCounted
			{
			public:
				idSWFScriptFunction_Accept() { }
				idSWFScriptVar Call( idSWFScriptObject* thisObject, const idSWFParmList& parms )
				{
					common->Dialog().ClearDialog( GDM_LEAVE_LOBBY_RET_MAIN );
					session->Cancel();
					
					return idSWFScriptVar();
				}
			};
			class idSWFScriptFunction_Cancel : public idSWFScriptFunction_RefCounted
			{
			public:
				idSWFScriptFunction_Cancel() { }
				idSWFScriptVar Call( idSWFScriptObject* thisObject, const idSWFParmList& parms )
				{
					common->Dialog().ClearDialog( GDM_LEAVE_LOBBY_RET_MAIN );
					return idSWFScriptVar();
				}
			};
			
			idLobbyBase& activeLobby = session->GetActivePlatformLobbyBase();
			
			if( activeLobby.GetNumActiveLobbyUsers() > 1 )
			{
				common->Dialog().AddDialog( GDM_LEAVE_LOBBY_RET_MAIN, DIALOG_ACCEPT_CANCEL, new( TAG_SWF ) idSWFScriptFunction_Accept(), new( TAG_SWF ) idSWFScriptFunction_Cancel(), false );
			}
			else
			{
				session->Cancel();
			}
			
			return true;
		}
		case WIDGET_ACTION_MUTE_PLAYER:
		{
		
			if( parms.Num() != 1 )
			{
				return true;
			}
			
			int index = parms[0].ToInteger();
			
			idLobbyBase& activeLobby = session->GetPartyLobbyBase();
			lobbyUserID_t luid = activeLobby.GetLobbyUserIdByOrdinal( index );
			if( luid.IsValid() )
			{
				session->ToggleLobbyUserVoiceMute( luid );
			}
			
			return true;
		}
		case WIDGET_ACTION_COMMAND:
		{
		
			if( options == NULL )
			{
				return true;
			}
			
			int selectionIndex = options->GetFocusIndex();
			if( parms.Num() > 1 )
			{
				selectionIndex = parms[1].ToInteger();
			}
			
			if( selectionIndex != options->GetFocusIndex() )
			{
				options->SetViewIndex( options->GetViewOffset() + selectionIndex );
				options->SetFocusIndex( selectionIndex );
			}
			
			switch( parms[0].ToInteger() )
			{
				case PARTY_CMD_QUICK:
				{
					idMatchParameters matchParameters = idMatchParameters( session->GetPartyLobbyBase().GetMatchParms() );
					
					// Reset these to random for quick match.
					matchParameters.gameMap =  GAME_MAP_RANDOM;
					matchParameters.gameMode = GAME_MODE_RANDOM;
					
					// Always a public match.
					matchParameters.matchFlags &= ~MATCH_INVITE_ONLY;
					
					session->UpdatePartyParms( matchParameters );
					
					// Update flags for game lobby.
					matchParameters.matchFlags = DefaultPartyFlags | DefaultPublicGameFlags;
					cvarSystem->MoveCVarsToDict( CVAR_SERVERINFO, matchParameters.serverInfo );
					
					// Force a default value for the si_timelimit and si_fraglimit for quickmatch
					matchParameters.serverInfo.SetInt( "si_timelimit", 15 );
					matchParameters.serverInfo.SetInt( "si_fraglimit", 10 );
					
					session->FindOrCreateMatch( matchParameters );
					break;
				}
				case PARTY_CMD_FIND:
				{
					menuData->SetNextScreen( SHELL_AREA_MODE_SELECT, MENU_TRANSITION_SIMPLE );
					break;
				}
				case PARTY_CMD_CREATE:
				{
					idMatchParameters matchParameters = idMatchParameters( session->GetPartyLobbyBase().GetMatchParms() );
					
					const bool isInviteOnly = MatchTypeInviteOnly( matchParameters.matchFlags );
					
					matchParameters.matchFlags = DefaultPartyFlags | DefaultPrivateGameFlags;
					
					if( isInviteOnly )
					{
						matchParameters.matchFlags |= MATCH_INVITE_ONLY;
					}
					
					int mode = idMath::ClampInt( -1, GAME_COUNT - 1, si_mode.GetInteger() );
					const idList< mpMap_t > maps = common->GetMapList();
					int map = idMath::ClampInt( -1, maps.Num() - 1, si_map.GetInteger() );
					
					matchParameters.gameMap = map;
					matchParameters.gameMode = mode;
					cvarSystem->MoveCVarsToDict( CVAR_SERVERINFO, matchParameters.serverInfo );
					session->CreateMatch( matchParameters );
					break;
				}
				case PARTY_CMD_PWF:
				{
					menuData->SetNextScreen( SHELL_AREA_BROWSER, MENU_TRANSITION_SIMPLE );
					break;
				}
				case PARTY_CMD_LEADERBOARDS:
				{
					ShowLeaderboards();
					break;
				}
				case PARTY_CMD_TOGGLE_PRIVACY:
				{
					idMatchParameters matchParameters = idMatchParameters( session->GetPartyLobbyBase().GetMatchParms() );
					matchParameters.matchFlags ^= MATCH_INVITE_ONLY;
					session->UpdatePartyParms( matchParameters );
					int bitSet = ( matchParameters.matchFlags & MATCH_INVITE_ONLY );
					net_inviteOnly.SetBool( bitSet != 0 ? true : false );
					break;
				}
				case PARTY_CMD_SHOW_PARTY_GAMES:
				{
					session->ShowPartySessions();
					break;
				}
				case PARTY_CMD_INVITE:
				{
					if( session->GetPartyLobbyBase().IsLobbyFull() )
					{
						common->Dialog().AddDialog( GDM_CANNOT_INVITE_LOBBY_FULL, DIALOG_CONTINUE, NULL, NULL, true, __FUNCTION__, __LINE__, false );
						return true;
					}
					
					InvitePartyOrFriends();
					break;
				}
			}
			
			return true;
		}
		case WIDGET_ACTION_START_REPEATER:
		{
		
			if( options == NULL )
			{
				return true;
			}
			
			if( parms.Num() == 4 )
			{
				int selectionIndex = parms[3].ToInteger();
				if( selectionIndex != options->GetFocusIndex() )
				{
					options->SetViewIndex( options->GetViewOffset() + selectionIndex );
					options->SetFocusIndex( selectionIndex );
				}
			}
			break;
		}
		case WIDGET_ACTION_SELECT_GAMERTAG:
		{
			int selectionIndex = lobby->GetFocusIndex();
			if( parms.Num() > 0 )
			{
				selectionIndex = parms[0].ToInteger();
			}
			
			if( selectionIndex != lobby->GetFocusIndex() )
			{
				lobby->SetViewIndex( lobby->GetViewOffset() + selectionIndex );
				lobby->SetFocusIndex( selectionIndex );
				return true;
			}
			
			idLobbyBase& activeLobby = session->GetPartyLobbyBase();
			lobbyUserID_t luid = activeLobby.GetLobbyUserIdByOrdinal( selectionIndex );
			if( luid.IsValid() )
			{
				session->ShowLobbyUserGamerCardUI( luid );
			}
			
			return true;
		}
	}
	
	return idMenuWidget::HandleAction( action, event, widget, forceHandled );
}
Пример #30
0
bool RB_RenderShadowMaps( viewLight_t* vLight ) {

	const idMaterial* lightShader = vLight->lightShader;

	if (lightShader->IsFogLight() || lightShader->IsBlendLight()) {
		return true;
	}

	if (!vLight->localInteractions && !vLight->globalInteractions
		&& !vLight->translucentInteractions) {
		return true;
	}

	if (!vLight->lightShader->LightCastsShadows()) {
		return true;
	}

	int lod = r_smForceLod.GetInteger();
	if(lod < 0) {
		lod = vLight->shadowMapLod;
	}
	lod = Max( 0, Min( lod, 2 ) );

	const uint64 startTime = Sys_Microseconds();

	const float polygonOffsetBias = vLight->lightDef->ShadowPolygonOffsetBias();
	const float polygonOffsetFactor = vLight->lightDef->ShadowPolygonOffsetFactor();
	glEnable( GL_POLYGON_OFFSET_FILL );
	glPolygonOffset( polygonOffsetFactor, polygonOffsetBias );

	switch (r_smFaceCullMode.GetInteger())
	{
	case 0:
		glEnable( GL_CULL_FACE );
		glFrontFace( GL_CCW );
		break;
	case 1:
		glEnable( GL_CULL_FACE );
		glFrontFace( GL_CW );
		break;
	case 2:
	default:
		glDisable( GL_CULL_FACE );
		break;
	}

	ShadowRenderList renderlist;
	int numShadowMaps = 0;

	if (vLight->lightDef->parms.parallel) {
		assert( vLight->lightDef->numShadowMapFrustums == 1 );
		shadowMapFrustum_t& frustum = vLight->lightDef->shadowMapFrustums[0];

		if (!shadowMapAllocator.Allocate( 0, 6, vLight->shadowCoords )) {
			return false;
		}

		const float cascadeDistances[6] = {
			r_smCascadeDistance0.GetFloat(),
			r_smCascadeDistance1.GetFloat(),
			r_smCascadeDistance2.GetFloat(),
			r_smCascadeDistance3.GetFloat(),
			r_smCascadeDistance4.GetFloat(),
			100000
		};

		lod = 0;
		float nextNearDistance = 1;
		for (int c = 0; c < 6; ++c) {
			idFrustum viewFrustum = backEnd.viewDef->viewFrustum;
			viewFrustum.MoveFarDistance( cascadeDistances[c] ); //move far before near, so far is always greater than near
			viewFrustum.MoveNearDistance( nextNearDistance );
			nextNearDistance = cascadeDistances[c];

			idVec3 viewCorners[8];
			viewFrustum.ToPoints( viewCorners );

			for (int i = 0; i < 8; ++i) {
				viewCorners[i] = frustum.viewMatrix * viewCorners[i];
			}

			idVec2 viewMinimum = viewCorners[0].ToVec2();
			idVec2 viewMaximum = viewCorners[0].ToVec2();

			for (int i = 1; i < 8; ++i) {
				const float x = viewCorners[i].x;
				const float y = viewCorners[i].y;

				viewMinimum.x = Min( viewMinimum.x, x );
				viewMinimum.y = Min( viewMinimum.y, y );

				viewMaximum.x = Max( viewMaximum.x, x );
				viewMaximum.y = Max( viewMaximum.y, y );
			}

			idVec2 minimum, maximum;

			if (c < r_smViewDependendCascades.GetInteger()) {
				minimum.x = Max( frustum.viewSpaceBounds[0].x, viewMinimum.x );
				minimum.y = Max( frustum.viewSpaceBounds[0].y, viewMinimum.y );
				maximum.x = Min( frustum.viewSpaceBounds[1].x, viewMaximum.x );
				maximum.y = Min( frustum.viewSpaceBounds[1].y, viewMaximum.y );
			}
			else {
				minimum = frustum.viewSpaceBounds[0].ToVec2();
				maximum = frustum.viewSpaceBounds[1].ToVec2();
			}

			float r = idMath::Abs( maximum.x - minimum.x ) * 0.5f;
			float l = -r;
			float t = idMath::Abs( maximum.y - minimum.y ) * 0.5f;
			float b = -t;

			vLight->viewMatrices[c] = frustum.viewMatrix;
			vLight->viewMatrices[c][12] = -(maximum.x + minimum.x) * 0.5f;
			vLight->viewMatrices[c][13] = -(maximum.y + minimum.y) * 0.5f;
			vLight->viewMatrices[c][14] = -(frustum.viewSpaceBounds[1].z + 1);

			const float f = fabs( frustum.viewSpaceBounds[1].z - frustum.viewSpaceBounds[0].z );
			const float n = 1;

			vLight->projectionMatrices[c] = fhRenderMatrix::identity;
			vLight->projectionMatrices[c][0] = 2.0f / (r - l);
			vLight->projectionMatrices[c][5] = 2.0f / (b - t);
			vLight->projectionMatrices[c][10] = -2.0f / (f - n);
			vLight->projectionMatrices[c][12] = -((r + l) / (r - l));
			vLight->projectionMatrices[c][13] = -((t + b) / (t - b));
			vLight->projectionMatrices[c][14] = -((f + n) / (f - n));
			vLight->projectionMatrices[c][15] = 1.0f;

			vLight->viewProjectionMatrices[c] = vLight->projectionMatrices[c] * vLight->viewMatrices[c];
			vLight->width[c] = fabs( r * 2 );
			vLight->height[c] = fabs( t * 2 );

			vLight->culled[c] = false;
		}

		renderlist.AddInteractions( vLight, nullptr, 0 );

		numShadowMaps = 6;
	}
	else if (vLight->lightDef->parms.pointLight) {
		assert( vLight->lightDef->numShadowMapFrustums == 6 );

		idVec3 viewCorners[8];
		backEnd.viewDef->viewFrustum.ToPoints( viewCorners );

		for (int i = 0; i < 6; ++i) {
			if (r_smLightSideCulling.GetBool()) {
				vLight->culled[i] = vLight->lightDef->shadowMapFrustums[i].Cull(viewCorners);
			}
			else {
				vLight->culled[i] = false;
			}

			if (vLight->culled[i]) {
				continue;
			}

			if (!shadowMapAllocator.Allocate(lod, 1, &vLight->shadowCoords[i])) {
				return false;
			}

			vLight->viewMatrices[i] = vLight->lightDef->shadowMapFrustums[i].viewMatrix;
			vLight->projectionMatrices[i] = vLight->lightDef->shadowMapFrustums[i].projectionMatrix;
			vLight->viewProjectionMatrices[i] = vLight->lightDef->shadowMapFrustums[i].viewProjectionMatrix;
		}

		renderlist.AddInteractions( vLight, vLight->lightDef->shadowMapFrustums, vLight->lightDef->numShadowMapFrustums );

		numShadowMaps = 6;
	}
	else {
		//projected light

		if (!shadowMapAllocator.Allocate( lod, 1, vLight->shadowCoords )) {
			return false;
		}

		assert( vLight->lightDef->numShadowMapFrustums == 1 );

		vLight->viewMatrices[0] = vLight->lightDef->shadowMapFrustums[0].viewMatrix;
		vLight->projectionMatrices[0] = vLight->lightDef->shadowMapFrustums[0].projectionMatrix;
		vLight->viewProjectionMatrices[0] = vLight->lightDef->shadowMapFrustums[0].viewProjectionMatrix;
		vLight->culled[0] = false;

		renderlist.AddInteractions( vLight, &vLight->lightDef->shadowMapFrustums[0], 1 );
		numShadowMaps = 1;
	}

	for (int side = 0; side < numShadowMaps; side++) {
		if(vLight->culled[side]) {
			continue;
		}

		const fhFramebuffer* framebuffer = fhFramebuffer::shadowmapFramebuffer;

		const int width = framebuffer->GetWidth() * vLight->shadowCoords[side].scale.x;
		const int height = framebuffer->GetHeight() * vLight->shadowCoords[side].scale.y;
		const int offsetX = framebuffer->GetWidth() * vLight->shadowCoords[side].offset.x;
		const int offsetY = framebuffer->GetHeight() * vLight->shadowCoords[side].offset.y;

		glViewport( offsetX, offsetY, width, height );
		glScissor( offsetX, offsetY, width, height );

		renderlist.Submit( vLight->viewMatrices[side].ToFloatPtr(), vLight->projectionMatrices[side].ToFloatPtr(), side, lod );
		backEnd.stats.groups[backEndGroup::ShadowMap0 + lod].passes += 1;
	}

	const uint64 endTime = Sys_Microseconds();
	backEnd.stats.groups[backEndGroup::ShadowMap0 + lod].time += static_cast<uint32>(endTime - startTime);

	return true;
}