Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 1
/*
2
Copyright (C) 1996-1997 Id Software, Inc.
3
 
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
 
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
 
13
See the GNU General Public License for more details.
14
 
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
 
19
*/
20
// sys_win.c -- Win32 system interface code
21
 
22
#include "quakedef.h"
23
#include "winquake.h"
24
#include "errno.h"
25
#include "resource.h"
26
#include "conproc.h"
27
 
28
#define MINIMUM_WIN_MEMORY		0x0880000
29
#define MAXIMUM_WIN_MEMORY		0x1000000
30
 
31
#define CONSOLE_ERROR_TIMEOUT	60.0	// # of seconds to wait on Sys_Error running
32
										//  dedicated before exiting
33
#define PAUSE_SLEEP		50				// sleep time on pause or minimization
34
#define NOT_FOCUS_SLEEP	20				// sleep time when not focus
35
 
36
int			starttime;
37
qboolean	ActiveApp, Minimized;
38
qboolean	WinNT;
39
 
40
static double		pfreq;
41
static double		curtime = 0.0;
42
static double		lastcurtime = 0.0;
43
static int			lowshift;
44
qboolean			isDedicated;
45
static qboolean		sc_return_on_enter = false;
46
HANDLE				hinput, houtput;
47
 
48
static char			*tracking_tag = "Clams & Mooses";
49
 
50
static HANDLE	tevent;
51
static HANDLE	hFile;
52
static HANDLE	heventParent;
53
static HANDLE	heventChild;
54
 
55
void MaskExceptions (void);
56
void Sys_InitFloatTime (void);
57
void Sys_PushFPCW_SetHigh (void);
58
void Sys_PopFPCW (void);
59
 
60
volatile int					sys_checksum;
61
 
62
 
63
/*
64
================
65
Sys_PageIn
66
================
67
*/
68
void Sys_PageIn (void *ptr, int size)
69
{
70
	byte	*x;
71
	int		j, m, n;
72
 
73
// touch all the memory to make sure it's there. The 16-page skip is to
74
// keep Win 95 from thinking we're trying to page ourselves in (we are
75
// doing that, of course, but there's no reason we shouldn't)
76
	x = (byte *)ptr;
77
 
78
	for (n=0 ; n<4 ; n++)
79
	{
80
		for (m=0 ; m<(size - 16 * 0x1000) ; m += 4)
81
		{
82
			sys_checksum += *(int *)&x[m];
83
			sys_checksum += *(int *)&x[m + 16 * 0x1000];
84
		}
85
	}
86
}
87
 
88
 
89
/*
90
===============================================================================
91
 
92
FILE IO
93
 
94
===============================================================================
95
*/
96
 
97
#define	MAX_HANDLES		10
98
FILE	*sys_handles[MAX_HANDLES];
99
 
100
int		findhandle (void)
101
{
102
	int		i;
103
 
104
	for (i=1 ; i
105
		if (!sys_handles[i])
106
			return i;
107
	Sys_Error ("out of handles");
108
	return -1;
109
}
110
 
111
/*
112
================
113
filelength
114
================
115
*/
116
int filelength (FILE *f)
117
{
118
	int		pos;
119
	int		end;
120
	int		t;
121
 
122
	t = VID_ForceUnlockedAndReturnState ();
123
 
124
	pos = ftell (f);
125
	fseek (f, 0, SEEK_END);
126
	end = ftell (f);
127
	fseek (f, pos, SEEK_SET);
128
 
129
	VID_ForceLockState (t);
130
 
131
	return end;
132
}
133
 
134
int Sys_FileOpenRead (char *path, int *hndl)
135
{
136
	FILE	*f;
137
	int		i, retval;
138
	int		t;
139
 
140
	t = VID_ForceUnlockedAndReturnState ();
141
 
142
	i = findhandle ();
143
 
144
	f = fopen(path, "rb");
145
 
146
	if (!f)
147
	{
148
		*hndl = -1;
149
		retval = -1;
150
	}
151
	else
152
	{
153
		sys_handles[i] = f;
154
		*hndl = i;
155
		retval = filelength(f);
156
	}
157
 
158
	VID_ForceLockState (t);
159
 
160
	return retval;
161
}
162
 
163
int Sys_FileOpenWrite (char *path)
164
{
165
	FILE	*f;
166
	int		i;
167
	int		t;
168
 
169
	t = VID_ForceUnlockedAndReturnState ();
170
 
171
	i = findhandle ();
172
 
173
	f = fopen(path, "wb");
174
	if (!f)
175
		Sys_Error ("Error opening %s: %s", path,strerror(errno));
176
	sys_handles[i] = f;
177
 
178
	VID_ForceLockState (t);
179
 
180
	return i;
181
}
182
 
183
void Sys_FileClose (int handle)
184
{
185
	int		t;
186
 
187
	t = VID_ForceUnlockedAndReturnState ();
188
	fclose (sys_handles[handle]);
189
	sys_handles[handle] = NULL;
190
	VID_ForceLockState (t);
191
}
192
 
193
void Sys_FileSeek (int handle, int position)
194
{
195
	int		t;
196
 
197
	t = VID_ForceUnlockedAndReturnState ();
198
	fseek (sys_handles[handle], position, SEEK_SET);
199
	VID_ForceLockState (t);
200
}
201
 
202
int Sys_FileRead (int handle, void *dest, int count)
203
{
204
	int		t, x;
205
 
206
	t = VID_ForceUnlockedAndReturnState ();
207
	x = fread (dest, 1, count, sys_handles[handle]);
208
	VID_ForceLockState (t);
209
	return x;
210
}
211
 
212
int Sys_FileWrite (int handle, void *data, int count)
213
{
214
	int		t, x;
215
 
216
	t = VID_ForceUnlockedAndReturnState ();
217
	x = fwrite (data, 1, count, sys_handles[handle]);
218
	VID_ForceLockState (t);
219
	return x;
220
}
221
 
222
int	Sys_FileTime (char *path)
223
{
224
	FILE	*f;
225
	int		t, retval;
226
 
227
	t = VID_ForceUnlockedAndReturnState ();
228
 
229
	f = fopen(path, "rb");
230
 
231
	if (f)
232
	{
233
		fclose(f);
234
		retval = 1;
235
	}
236
	else
237
	{
238
		retval = -1;
239
	}
240
 
241
	VID_ForceLockState (t);
242
	return retval;
243
}
244
 
245
void Sys_mkdir (char *path)
246
{
247
	_mkdir (path);
248
}
249
 
250
 
251
/*
252
===============================================================================
253
 
254
SYSTEM IO
255
 
256
===============================================================================
257
*/
258
 
259
/*
260
================
261
Sys_MakeCodeWriteable
262
================
263
*/
264
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
265
{
266
	DWORD  flOldProtect;
267
 
268
	if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect))
269
   		Sys_Error("Protection change failed\n");
270
}
271
 
272
 
273
#ifndef _M_IX86
274
 
275
void Sys_SetFPCW (void)
276
{
277
}
278
 
279
void Sys_PushFPCW_SetHigh (void)
280
{
281
}
282
 
283
void Sys_PopFPCW (void)
284
{
285
}
286
 
287
void MaskExceptions (void)
288
{
289
}
290
 
291
#endif
292
 
293
/*
294
================
295
Sys_Init
296
================
297
*/
298
void Sys_Init (void)
299
{
300
	LARGE_INTEGER	PerformanceFreq;
301
	unsigned int	lowpart, highpart;
302
	OSVERSIONINFO	vinfo;
303
 
304
	MaskExceptions ();
305
	Sys_SetFPCW ();
306
 
307
	if (!QueryPerformanceFrequency (&PerformanceFreq))
308
		Sys_Error ("No hardware timer available");
309
 
310
// get 32 out of the 64 time bits such that we have around
311
// 1 microsecond resolution
312
	lowpart = (unsigned int)PerformanceFreq.LowPart;
313
	highpart = (unsigned int)PerformanceFreq.HighPart;
314
	lowshift = 0;
315
 
316
	while (highpart || (lowpart > 2000000.0))
317
	{
318
		lowshift++;
319
		lowpart >>= 1;
320
		lowpart |= (highpart & 1) << 31;
321
		highpart >>= 1;
322
	}
323
 
324
	pfreq = 1.0 / (double)lowpart;
325
 
326
	Sys_InitFloatTime ();
327
 
328
	vinfo.dwOSVersionInfoSize = sizeof(vinfo);
329
 
330
	if (!GetVersionEx (&vinfo))
331
		Sys_Error ("Couldn't get OS info");
332
 
333
	if ((vinfo.dwMajorVersion < 4) ||
334
		(vinfo.dwPlatformId == VER_PLATFORM_WIN32s))
335
	{
336
		Sys_Error ("WinQuake requires at least Win95 or NT 4.0");
337
	}
338
 
339
	if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
340
		WinNT = true;
341
	else
342
		WinNT = false;
343
}
344
 
345
 
346
void Sys_Error (char *error, ...)
347
{
348
	va_list		argptr;
349
	char		text[1024], text2[1024];
350
	char		*text3 = "Press Enter to exit\n";
351
	char		*text4 = "***********************************\n";
352
	char		*text5 = "\n";
353
	DWORD		dummy;
354
	double		starttime;
355
	static int	in_sys_error0 = 0;
356
	static int	in_sys_error1 = 0;
357
	static int	in_sys_error2 = 0;
358
	static int	in_sys_error3 = 0;
359
 
360
	if (!in_sys_error3)
361
	{
362
		in_sys_error3 = 1;
363
		VID_ForceUnlockedAndReturnState ();
364
	}
365
 
366
	va_start (argptr, error);
367
	vsprintf (text, error, argptr);
368
	va_end (argptr);
369
 
370
	if (isDedicated)
371
	{
372
		va_start (argptr, error);
373
		vsprintf (text, error, argptr);
374
		va_end (argptr);
375
 
376
		sprintf (text2, "ERROR: %s\n", text);
377
		WriteFile (houtput, text5, strlen (text5), &dummy, NULL);
378
		WriteFile (houtput, text4, strlen (text4), &dummy, NULL);
379
		WriteFile (houtput, text2, strlen (text2), &dummy, NULL);
380
		WriteFile (houtput, text3, strlen (text3), &dummy, NULL);
381
		WriteFile (houtput, text4, strlen (text4), &dummy, NULL);
382
 
383
 
384
		starttime = Sys_FloatTime ();
385
		sc_return_on_enter = true;	// so Enter will get us out of here
386
 
387
		while (!Sys_ConsoleInput () &&
388
				((Sys_FloatTime () - starttime) < CONSOLE_ERROR_TIMEOUT))
389
		{
390
		}
391
	}
392
	else
393
	{
394
	// switch to windowed so the message box is visible, unless we already
395
	// tried that and failed
396
		if (!in_sys_error0)
397
		{
398
			in_sys_error0 = 1;
399
			VID_SetDefaultMode ();
400
			MessageBox(NULL, text, "Quake Error",
401
					   MB_OK | MB_SETFOREGROUND | MB_ICONSTOP);
402
		}
403
		else
404
		{
405
			MessageBox(NULL, text, "Double Quake Error",
406
					   MB_OK | MB_SETFOREGROUND | MB_ICONSTOP);
407
		}
408
	}
409
 
410
	if (!in_sys_error1)
411
	{
412
		in_sys_error1 = 1;
413
		Host_Shutdown ();
414
	}
415
 
416
// shut down QHOST hooks if necessary
417
	if (!in_sys_error2)
418
	{
419
		in_sys_error2 = 1;
420
		DeinitConProc ();
421
	}
422
 
423
	exit (1);
424
}
425
 
426
void Sys_Printf (char *fmt, ...)
427
{
428
	va_list		argptr;
429
	char		text[1024];
430
	DWORD		dummy;
431
 
432
	if (isDedicated)
433
	{
434
		va_start (argptr,fmt);
435
		vsprintf (text, fmt, argptr);
436
		va_end (argptr);
437
 
438
		WriteFile(houtput, text, strlen (text), &dummy, NULL);
439
	}
440
}
441
 
442
void Sys_Quit (void)
443
{
444
 
445
	VID_ForceUnlockedAndReturnState ();
446
 
447
	Host_Shutdown();
448
 
449
	if (tevent)
450
		CloseHandle (tevent);
451
 
452
	if (isDedicated)
453
		FreeConsole ();
454
 
455
// shut down QHOST hooks if necessary
456
	DeinitConProc ();
457
 
458
	exit (0);
459
}
460
 
461
 
462
/*
463
================
464
Sys_FloatTime
465
================
466
*/
467
double Sys_FloatTime (void)
468
{
469
	static int			sametimecount;
470
	static unsigned int	oldtime;
471
	static int			first = 1;
472
	LARGE_INTEGER		PerformanceCount;
473
	unsigned int		temp, t2;
474
	double				time;
475
 
476
	Sys_PushFPCW_SetHigh ();
477
 
478
	QueryPerformanceCounter (&PerformanceCount);
479
 
480
	temp = ((unsigned int)PerformanceCount.LowPart >> lowshift) |
481
		   ((unsigned int)PerformanceCount.HighPart << (32 - lowshift));
482
 
483
	if (first)
484
	{
485
		oldtime = temp;
486
		first = 0;
487
	}
488
	else
489
	{
490
	// check for turnover or backward time
491
		if ((temp <= oldtime) && ((oldtime - temp) < 0x10000000))
492
		{
493
			oldtime = temp;	// so we can't get stuck
494
		}
495
		else
496
		{
497
			t2 = temp - oldtime;
498
 
499
			time = (double)t2 * pfreq;
500
			oldtime = temp;
501
 
502
			curtime += time;
503
 
504
			if (curtime == lastcurtime)
505
			{
506
				sametimecount++;
507
 
508
				if (sametimecount > 100000)
509
				{
510
					curtime += 1.0;
511
					sametimecount = 0;
512
				}
513
			}
514
			else
515
			{
516
				sametimecount = 0;
517
			}
518
 
519
			lastcurtime = curtime;
520
		}
521
	}
522
 
523
	Sys_PopFPCW ();
524
 
525
    return curtime;
526
}
527
 
528
 
529
/*
530
================
531
Sys_InitFloatTime
532
================
533
*/
534
void Sys_InitFloatTime (void)
535
{
536
	int		j;
537
 
538
	Sys_FloatTime ();
539
 
540
	j = COM_CheckParm("-starttime");
541
 
542
	if (j)
543
	{
544
		curtime = (double) (Q_atof(com_argv[j+1]));
545
	}
546
	else
547
	{
548
		curtime = 0.0;
549
	}
550
 
551
	lastcurtime = curtime;
552
}
553
 
554
 
555
char *Sys_ConsoleInput (void)
556
{
557
	static char	text[256];
558
	static int		len;
559
	INPUT_RECORD	recs[1024];
560
	int		count;
561
	int		i, dummy;
562
	int		ch, numread, numevents;
563
 
564
	if (!isDedicated)
565
		return NULL;
566
 
567
 
568
	for ( ;; )
569
	{
570
		if (!GetNumberOfConsoleInputEvents (hinput, &numevents))
571
			Sys_Error ("Error getting # of console events");
572
 
573
		if (numevents <= 0)
574
			break;
575
 
576
		if (!ReadConsoleInput(hinput, recs, 1, &numread))
577
			Sys_Error ("Error reading console input");
578
 
579
		if (numread != 1)
580
			Sys_Error ("Couldn't read console input");
581
 
582
		if (recs[0].EventType == KEY_EVENT)
583
		{
584
			if (!recs[0].Event.KeyEvent.bKeyDown)
585
			{
586
				ch = recs[0].Event.KeyEvent.uChar.AsciiChar;
587
 
588
				switch (ch)
589
				{
590
					case '\r':
591
						WriteFile(houtput, "\r\n", 2, &dummy, NULL);
592
 
593
						if (len)
594
						{
595
							text[len] = 0;
596
							len = 0;
597
							return text;
598
						}
599
						else if (sc_return_on_enter)
600
						{
601
						// special case to allow exiting from the error handler on Enter
602
							text[0] = '\r';
603
							len = 0;
604
							return text;
605
						}
606
 
607
						break;
608
 
609
					case '\b':
610
						WriteFile(houtput, "\b \b", 3, &dummy, NULL);
611
						if (len)
612
						{
613
							len--;
614
						}
615
						break;
616
 
617
					default:
618
						if (ch >= ' ')
619
						{
620
							WriteFile(houtput, &ch, 1, &dummy, NULL);
621
							text[len] = ch;
622
							len = (len + 1) & 0xff;
623
						}
624
 
625
						break;
626
 
627
				}
628
			}
629
		}
630
	}
631
 
632
	return NULL;
633
}
634
 
635
void Sys_Sleep (void)
636
{
637
	Sleep (1);
638
}
639
 
640
 
641
void Sys_SendKeyEvents (void)
642
{
643
    MSG        msg;
644
 
645
	while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
646
	{
647
	// we always update if there are any event, even if we're paused
648
		scr_skipupdate = 0;
649
 
650
		if (!GetMessage (&msg, NULL, 0, 0))
651
			Sys_Quit ();
652
 
653
      	TranslateMessage (&msg);
654
      	DispatchMessage (&msg);
655
	}
656
}
657
 
658
 
659
/*
660
==============================================================================
661
 
662
 WINDOWS CRAP
663
 
664
==============================================================================
665
*/
666
 
667
 
668
/*
669
==================
670
WinMain
671
==================
672
*/
673
void SleepUntilInput (int time)
674
{
675
 
676
	MsgWaitForMultipleObjects(1, &tevent, FALSE, time, QS_ALLINPUT);
677
}
678
 
679
 
680
/*
681
==================
682
WinMain
683
==================
684
*/
685
HINSTANCE	global_hInstance;
686
int			global_nCmdShow;
687
char		*argv[MAX_NUM_ARGVS];
688
static char	*empty_string = "";
689
HWND		hwnd_dialog;
690
 
691
 
692
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
693
{
694
    MSG				msg;
695
	quakeparms_t	parms;
696
	double			time, oldtime, newtime;
697
	MEMORYSTATUS	lpBuffer;
698
	static	char	cwd[1024];
699
	int				t;
700
	RECT			rect;
701
 
702
    /* previous instances do not exist in Win32 */
703
    if (hPrevInstance)
704
        return 0;
705
 
706
	global_hInstance = hInstance;
707
	global_nCmdShow = nCmdShow;
708
 
709
	lpBuffer.dwLength = sizeof(MEMORYSTATUS);
710
	GlobalMemoryStatus (&lpBuffer);
711
 
712
	if (!GetCurrentDirectory (sizeof(cwd), cwd))
713
		Sys_Error ("Couldn't determine current directory");
714
 
715
	if (cwd[Q_strlen(cwd)-1] == '/')
716
		cwd[Q_strlen(cwd)-1] = 0;
717
 
718
	parms.basedir = cwd;
719
	parms.cachedir = NULL;
720
 
721
	parms.argc = 1;
722
	argv[0] = empty_string;
723
 
724
	while (*lpCmdLine && (parms.argc < MAX_NUM_ARGVS))
725
	{
726
		while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
727
			lpCmdLine++;
728
 
729
		if (*lpCmdLine)
730
		{
731
			argv[parms.argc] = lpCmdLine;
732
			parms.argc++;
733
 
734
			while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
735
				lpCmdLine++;
736
 
737
			if (*lpCmdLine)
738
			{
739
				*lpCmdLine = 0;
740
				lpCmdLine++;
741
			}
742
 
743
		}
744
	}
745
 
746
	parms.argv = argv;
747
 
748
	COM_InitArgv (parms.argc, parms.argv);
749
 
750
	parms.argc = com_argc;
751
	parms.argv = com_argv;
752
 
753
	isDedicated = (COM_CheckParm ("-dedicated") != 0);
754
 
755
	if (!isDedicated)
756
	{
757
		hwnd_dialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, NULL);
758
 
759
		if (hwnd_dialog)
760
		{
761
			if (GetWindowRect (hwnd_dialog, &rect))
762
			{
763
				if (rect.left > (rect.top * 2))
764
				{
765
					SetWindowPos (hwnd_dialog, 0,
766
						(rect.left / 2) - ((rect.right - rect.left) / 2),
767
						rect.top, 0, 0,
768
						SWP_NOZORDER | SWP_NOSIZE);
769
				}
770
			}
771
 
772
			ShowWindow (hwnd_dialog, SW_SHOWDEFAULT);
773
			UpdateWindow (hwnd_dialog);
774
			SetForegroundWindow (hwnd_dialog);
775
		}
776
	}
777
 
778
// take the greater of all the available memory or half the total memory,
779
// but at least 8 Mb and no more than 16 Mb, unless they explicitly
780
// request otherwise
781
	parms.memsize = lpBuffer.dwAvailPhys;
782
 
783
	if (parms.memsize < MINIMUM_WIN_MEMORY)
784
		parms.memsize = MINIMUM_WIN_MEMORY;
785
 
786
	if (parms.memsize < (lpBuffer.dwTotalPhys >> 1))
787
		parms.memsize = lpBuffer.dwTotalPhys >> 1;
788
 
789
	if (parms.memsize > MAXIMUM_WIN_MEMORY)
790
		parms.memsize = MAXIMUM_WIN_MEMORY;
791
 
792
	if (COM_CheckParm ("-heapsize"))
793
	{
794
		t = COM_CheckParm("-heapsize") + 1;
795
 
796
		if (t < com_argc)
797
			parms.memsize = Q_atoi (com_argv[t]) * 1024;
798
	}
799
 
800
	parms.membase = malloc (parms.memsize);
801
 
802
	if (!parms.membase)
803
		Sys_Error ("Not enough memory free; check disk space\n");
804
 
805
	Sys_PageIn (parms.membase, parms.memsize);
806
 
807
	tevent = CreateEvent(NULL, FALSE, FALSE, NULL);
808
 
809
	if (!tevent)
810
		Sys_Error ("Couldn't create event");
811
 
812
	if (isDedicated)
813
	{
814
		if (!AllocConsole ())
815
		{
816
			Sys_Error ("Couldn't create dedicated server console");
817
		}
818
 
819
		hinput = GetStdHandle (STD_INPUT_HANDLE);
820
		houtput = GetStdHandle (STD_OUTPUT_HANDLE);
821
 
822
	// give QHOST a chance to hook into the console
823
		if ((t = COM_CheckParm ("-HFILE")) > 0)
824
		{
825
			if (t < com_argc)
826
				hFile = (HANDLE)Q_atoi (com_argv[t+1]);
827
		}
828
 
829
		if ((t = COM_CheckParm ("-HPARENT")) > 0)
830
		{
831
			if (t < com_argc)
832
				heventParent = (HANDLE)Q_atoi (com_argv[t+1]);
833
		}
834
 
835
		if ((t = COM_CheckParm ("-HCHILD")) > 0)
836
		{
837
			if (t < com_argc)
838
				heventChild = (HANDLE)Q_atoi (com_argv[t+1]);
839
		}
840
 
841
		InitConProc (hFile, heventParent, heventChild);
842
	}
843
 
844
	Sys_Init ();
845
 
846
// because sound is off until we become active
847
	S_BlockSound ();
848
 
849
	Sys_Printf ("Host_Init\n");
850
	Host_Init (&parms);
851
 
852
	oldtime = Sys_FloatTime ();
853
 
854
    /* main window message loop */
855
	while (1)
856
	{
857
		if (isDedicated)
858
		{
859
			newtime = Sys_FloatTime ();
860
			time = newtime - oldtime;
861
 
862
			while (time < sys_ticrate.value )
863
			{
864
				Sys_Sleep();
865
				newtime = Sys_FloatTime ();
866
				time = newtime - oldtime;
867
			}
868
		}
869
		else
870
		{
871
		// yield the CPU for a little while when paused, minimized, or not the focus
872
			if ((cl.paused && (!ActiveApp && !DDActive)) || Minimized || block_drawing)
873
			{
874
				SleepUntilInput (PAUSE_SLEEP);
875
				scr_skipupdate = 1;		// no point in bothering to draw
876
			}
877
			else if (!ActiveApp && !DDActive)
878
			{
879
				SleepUntilInput (NOT_FOCUS_SLEEP);
880
			}
881
 
882
			newtime = Sys_FloatTime ();
883
			time = newtime - oldtime;
884
		}
885
 
886
		Host_Frame (time);
887
		oldtime = newtime;
888
	}
889
 
890
    /* return success of application */
891
    return TRUE;
892
}
893