Index: framework/Common.cpp
===================================================================
--- framework/Common.cpp	(revision 7565)
+++ framework/Common.cpp	(working copy)
@@ -2519,8 +2519,7 @@
 #define MAX_ASYNC_STATS			1024
 
 asyncStats_t	com_asyncStats[MAX_ASYNC_STATS];		// indexed by com_ticNumber
-int prevAsyncMsec;
-int	lastTicMsec;
+int64_t lastTicUsec;
 
 void idCommonLocal::SingleAsyncTic( void ) {
 	// main thread code can prevent this from happening while modifying
@@ -2571,31 +2570,31 @@
 		return;
 	}
 
-	const int msec = Sys_Milliseconds();
-	if ( !lastTicMsec ) {
-		lastTicMsec = msec - USERCMD_MSEC;
+	const int64_t usec = Sys_GetTimeMicroseconds();
+	if ( !lastTicUsec ) {
+		lastTicUsec = usec - USERCMD_USEC;
 	}
 
-	int ticMsec = USERCMD_MSEC;
+	int64_t ticUsec = USERCMD_USEC;
 	const float timescale = com_timescale.GetFloat();
 
 	// don't skip too many
 	if ( timescale == 1.0f ) {
-		if ( lastTicMsec + (10 * USERCMD_MSEC) < msec ) {
-			lastTicMsec = msec - (10 * USERCMD_MSEC);
+		if ( lastTicUsec + (10 * USERCMD_USEC) < usec ) {
+			lastTicUsec = usec - (10 * USERCMD_USEC);
 		}
 	}
 	// the number of msec per tic can be varies with the timescale cvar
 	else {								// i.e if ( timescale != 1.0f )
-		ticMsec /= timescale;
-		if ( ticMsec < 1 ) {
-			ticMsec = 1;
+		ticUsec /= timescale;
+		if ( ticUsec < 1 ) {
+			ticUsec = 1;
 		}
 	}
 
-	while ( lastTicMsec + ticMsec <= msec ) {
+	while ( lastTicUsec + ticUsec <= usec ) {
 		SingleAsyncTic();
-		lastTicMsec += ticMsec;
+		lastTicUsec += ticUsec;
 	}
 }
 
Index: framework/UsercmdGen.h
===================================================================
--- framework/UsercmdGen.h	(revision 7565)
+++ framework/UsercmdGen.h	(working copy)
@@ -27,6 +27,9 @@
 const int USERCMD_HZ			= 60;			// 60 frames per second
 const int USERCMD_MSEC			= 1000 / USERCMD_HZ;
 
+//stgatilov: this macros is used only for synchronizing main tic with vsync
+const int USERCMD_USEC			= 16650;		// ~60.06 Hz --- a bit higher than vsync
+
 // ButtonState inputs; originally from UsercmdGen.cpp, left out of SDK by accident
 // sourced from http://www.doom3world.org/phpbb2/viewtopic.php?f=26&t=18587&p=170143
 typedef enum {
Index: sys/win32/win_main.cpp
===================================================================
--- sys/win32/win_main.cpp	(revision 7565)
+++ sys/win32/win_main.cpp	(working copy)
@@ -1015,9 +1015,14 @@
 		common->Error( "idPacketServer::Spawn: CreateWaitableTimer failed" );
 	}
 
+	//stgatilov: run idCommonLocal::Async every 3 ms
+	//ideally, game tic should be incremented every 16.66 ms, but we cannot specify interval up to microseconds
+	//incrementing it every 16 ms causes double frames =( so we do it simply more often
+	const int intervalMS = 3;		//USERCMD_MSEC;
+
 	LARGE_INTEGER	t;
 	t.HighPart = t.LowPart = 0;
-	SetWaitableTimer( hTimer, &t, USERCMD_MSEC, NULL, NULL, TRUE );
+	SetWaitableTimer( hTimer, &t, intervalMS, NULL, NULL, TRUE );
 
     Sys_CreateThread( Sys_AsyncThread, NULL, THREAD_ABOVE_NORMAL, threadInfo, "Async", g_threads,  &g_thread_count );
 
