Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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
#include 
21
#include 
22
#include 
23
#include 
24
#include 
25
#include 
26
#include 
27
#include 
28
#include 
29
#include 
30
#include 
31
#include 
32
#include 
33
#include 
34
#include 
35
#include 
36
#include 
37
 
38
#include "quakedef.h"
39
#include "dosisms.h"
40
 
41
#define MINIMUM_WIN_MEMORY			0x800000
42
#define MINIMUM_WIN_MEMORY_LEVELPAK	(MINIMUM_WIN_MEMORY + 0x100000)
43
 
44
int			end_of_memory;
45
qboolean	lockmem, lockunlockmem, unlockmem;
46
static int	win95;
47
 
48
#define STDOUT	1
49
 
50
#define	KEYBUF_SIZE	256
51
static unsigned char	keybuf[KEYBUF_SIZE];
52
static int				keybuf_head=0;
53
static int				keybuf_tail=0;
54
 
55
static quakeparms_t	quakeparms;
56
int					sys_checksum;
57
static double		curtime = 0.0;
58
static double		lastcurtime = 0.0;
59
static double		oldtime = 0.0;
60
 
61
static qboolean		isDedicated;
62
 
63
static int			minmem;
64
 
65
float				fptest_temp;
66
 
67
extern char	start_of_memory __asm__("start");
68
 
69
//=============================================================================
70
 
71
// this is totally dependent on cwsdpmi putting the stack right after tge
72
// global data
73
 
74
// This does evil things in a Win95 DOS box!!!
75
#if 0
76
extern byte end;
77
#define	CHECKBYTE	0xed
78
void Sys_InitStackCheck (void)
79
{
80
	int		i;
81
 
82
	for (i=0 ; i<128*1024 ; i++)
83
		(&end)[i] = CHECKBYTE;
84
}
85
 
86
void Sys_StackCheck (void)
87
{
88
	int		i;
89
 
90
	for (i=0 ; i<128*1024 ; i++)
91
		if ( (&end)[i] != CHECKBYTE )
92
			break;
93
 
94
	Con_Printf ("%i undisturbed stack bytes\n", i);
95
	if (end != CHECKBYTE)
96
		Sys_Error ("System stack overflow!");
97
}
98
#endif
99
 
100
//=============================================================================
101
 
102
byte        scantokey[128] =
103
					{
104
//  0           1       2       3       4       5       6       7
105
//  8           9       A       B       C       D       E       F
106
 
107
	'7',    '8',    '9',    '0',    '-',    '=',    K_BACKSPACE, 9, // 0
108
	'q',    'w',    'e',    'r',    't',    'y',    'u',    'i',
109
	'o',    'p',    '[',    ']',    13 ,    K_CTRL,'a',  's',      // 1
110
	'd',    'f',    'g',    'h',    'j',    'k',    'l',    ';',
111
	'\'' ,    '`',    K_SHIFT,'\\',  'z',    'x',    'c',    'v',      // 2
112
	'b',    'n',    'm',    ',',    '.',    '/',    K_SHIFT,'*',
113
	K_ALT,' ',   0  ,    K_F1, K_F2, K_F3, K_F4, K_F5,   // 3
114
	K_F6, K_F7, K_F8, K_F9, K_F10,0  ,    0  , K_HOME,
115
	K_UPARROW,K_PGUP,'-',K_LEFTARROW,'5',K_RIGHTARROW,'+',K_END, //4
116
	K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0,             0,              K_F11,
117
	K_F12,0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 5
118
 
119
 
120
 
121
 
122
					};
123
 
124
byte        shiftscantokey[128] =
125
					{
126
//  0           1       2       3       4       5       6       7
127
//  8           9       A       B       C       D       E       F
128
 
129
	'&',    '*',    '(',    ')',    '_',    '+',    K_BACKSPACE, 9, // 0
130
	'Q',    'W',    'E',    'R',    'T',    'Y',    'U',    'I',
131
	'O',    'P',    '{',    '}',    13 ,    K_CTRL,'A',  'S',      // 1
132
	'D',    'F',    'G',    'H',    'J',    'K',    'L',    ':',
133
	'"' ,    '~',    K_SHIFT,'|',  'Z',    'X',    'C',    'V',      // 2
134
	'B',    'N',    'M',    '<',    '>',    '?',    K_SHIFT,'*',
135
	K_ALT,' ',   0  ,    K_F1, K_F2, K_F3, K_F4, K_F5,   // 3
136
	K_F6, K_F7, K_F8, K_F9, K_F10,0  ,    0  , K_HOME,
137
	K_UPARROW,K_PGUP,'_',K_LEFTARROW,'%',K_RIGHTARROW,'+',K_END, //4
138
	K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0,             0,              K_F11,
139
	K_F12,0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 5
140
 
141
 
142
 
143
 
144
					};
145
 
146
void TrapKey(void)
147
{
148
//	static int ctrl=0;
149
	keybuf[keybuf_head] = dos_inportb(0x60);
150
	dos_outportb(0x20, 0x20);
151
	/*
152
	if (scantokey[keybuf[keybuf_head]&0x7f] == K_CTRL)
153
		ctrl=keybuf[keybuf_head]&0x80;
154
	if (ctrl && scantokey[keybuf[keybuf_head]&0x7f] == 'c')
155
		Sys_Error("ctrl-c hit\n");
156
	*/
157
	keybuf_head = (keybuf_head + 1) & (KEYBUF_SIZE-1);
158
}
159
 
160
#define SC_UPARROW              0x48
161
#define SC_DOWNARROW    0x50
162
#define SC_LEFTARROW            0x4b
163
#define SC_RIGHTARROW   0x4d
164
#define SC_LEFTSHIFT   0x2a
165
#define SC_RIGHTSHIFT   0x36
166
#define SC_RIGHTARROW   0x4d
167
 
168
void MaskExceptions (void);
169
void Sys_InitFloatTime (void);
170
void Sys_PushFPCW_SetHigh (void);
171
void Sys_PopFPCW (void);
172
 
173
#define LEAVE_FOR_CACHE (512*1024)		//FIXME: tune
174
#define LOCKED_FOR_MALLOC (128*1024)	//FIXME: tune
175
 
176
 
177
void Sys_DetectWin95 (void)
178
{
179
	__dpmi_regs				r;
180
 
181
	r.x.ax = 0x160a;		/* Get Windows Version */
182
	__dpmi_int(0x2f, &r);
183
 
184
	if(r.x.ax || r.h.bh < 4)	/* Not windows or earlier than Win95 */
185
	{
186
		win95 = 0;
187
		lockmem = true;
188
		lockunlockmem = false;
189
		unlockmem = true;
190
	}
191
	else
192
	{
193
		win95 = 1;
194
		lockunlockmem = COM_CheckParm ("-winlockunlock");
195
 
196
		if (lockunlockmem)
197
			lockmem = true;
198
		else
199
			lockmem = COM_CheckParm ("-winlock");
200
 
201
		unlockmem = lockmem && !lockunlockmem;
202
	}
203
}
204
 
205
 
206
void *dos_getmaxlockedmem(int *size)
207
{
208
	__dpmi_free_mem_info	meminfo;
209
	__dpmi_meminfo			info;
210
	int						working_size;
211
	void					*working_memory;
212
	int						last_locked;
213
	int						extra, 	i, j, allocsize;
214
	static char				*msg = "Locking data...";
215
	int						m, n;
216
	byte					*x;
217
 
218
// first lock all the current executing image so the locked count will
219
// be accurate.  It doesn't hurt to lock the memory multiple times
220
	last_locked = __djgpp_selector_limit + 1;
221
	info.size = last_locked - 4096;
222
	info.address = __djgpp_base_address + 4096;
223
 
224
	if (lockmem)
225
	{
226
		if(__dpmi_lock_linear_region(&info))
227
		{
228
			Sys_Error ("Lock of current memory at 0x%lx for %ldKb failed!\n",
229
						info.address, info.size/1024);
230
		}
231
	}
232
 
233
	__dpmi_get_free_memory_information(&meminfo);
234
 
235
	if (!win95)		/* Not windows or earlier than Win95 */
236
	{
237
		working_size = meminfo.maximum_locked_page_allocation_in_pages * 4096;
238
	}
239
	else
240
	{
241
		working_size = meminfo.largest_available_free_block_in_bytes -
242
				LEAVE_FOR_CACHE;
243
	}
244
 
245
	working_size &= ~0xffff;		/* Round down to 64K */
246
	working_size += 0x10000;
247
 
248
	do
249
	{
250
		working_size -= 0x10000;		/* Decrease 64K and try again */
251
		working_memory = sbrk(working_size);
252
	} while (working_memory == (void *)-1);
253
 
254
	extra = 0xfffc - ((unsigned)sbrk(0) & 0xffff);
255
 
256
	if (extra > 0)
257
	{
258
		sbrk(extra);
259
		working_size += extra;
260
	}
261
 
262
// now grab the memory
263
	info.address = last_locked + __djgpp_base_address;
264
 
265
	if (!win95)
266
	{
267
	    info.size = __djgpp_selector_limit + 1 - last_locked;
268
 
269
		while (info.size > 0 && __dpmi_lock_linear_region(&info))
270
		{
271
			info.size -= 0x1000;
272
			working_size -= 0x1000;
273
			sbrk(-0x1000);
274
		}
275
	}
276
	else
277
	{			/* Win95 section */
278
		j = COM_CheckParm("-winmem");
279
 
280
		if (standard_quake)
281
			minmem = MINIMUM_WIN_MEMORY;
282
		else
283
			minmem = MINIMUM_WIN_MEMORY_LEVELPAK;
284
 
285
		if (j)
286
		{
287
			allocsize = ((int)(Q_atoi(com_argv[j+1]))) * 0x100000 +
288
					LOCKED_FOR_MALLOC;
289
 
290
			if (allocsize < (minmem + LOCKED_FOR_MALLOC))
291
				allocsize = minmem + LOCKED_FOR_MALLOC;
292
		}
293
		else
294
		{
295
			allocsize = minmem + LOCKED_FOR_MALLOC;
296
		}
297
 
298
		if (!lockmem)
299
		{
300
		// we won't lock, just sbrk the memory
301
			info.size = allocsize;
302
			goto UpdateSbrk;
303
		}
304
 
305
		// lock the memory down
306
		write (STDOUT, msg, strlen (msg));
307
 
308
		for (j=allocsize ; j>(minmem + LOCKED_FOR_MALLOC) ;
309
			 j -= 0x100000)
310
		{
311
			info.size = j;
312
 
313
			if (!__dpmi_lock_linear_region(&info))
314
				goto Locked;
315
 
316
			write (STDOUT, ".", 1);
317
		}
318
 
319
	// finally, try with the absolute minimum amount
320
		for (i=0 ; i<10 ; i++)
321
		{
322
			info.size = minmem + LOCKED_FOR_MALLOC;
323
 
324
			if (!__dpmi_lock_linear_region(&info))
325
				goto Locked;
326
		}
327
 
328
		Sys_Error ("Can't lock memory; %d Mb lockable RAM required. "
329
				   "Try shrinking smartdrv.", info.size / 0x100000);
330
 
331
Locked:
332
 
333
UpdateSbrk:
334
 
335
		info.address += info.size;
336
		info.address -= __djgpp_base_address + 4; // ending point, malloc align
337
		working_size = info.address - (int)working_memory;
338
		sbrk(info.address-(int)sbrk(0));		// negative adjustment
339
	}
340
 
341
 
342
	if (lockunlockmem)
343
	{
344
		__dpmi_unlock_linear_region (&info);
345
		printf ("Locked and unlocked %d Mb data\n", working_size / 0x100000);
346
	}
347
	else if (lockmem)
348
	{
349
		printf ("Locked %d Mb data\n", working_size / 0x100000);
350
	}
351
	else
352
	{
353
		printf ("Allocated %d Mb data\n", working_size / 0x100000);
354
	}
355
 
356
// touch all the memory to make sure it's there. The 16-page skip is to
357
// keep Win 95 from thinking we're trying to page ourselves in (we are
358
// doing that, of course, but there's no reason we shouldn't)
359
	x = (byte *)working_memory;
360
 
361
	for (n=0 ; n<4 ; n++)
362
	{
363
		for (m=0 ; m<(working_size - 16 * 0x1000) ; m += 4)
364
		{
365
			sys_checksum += *(int *)&x[m];
366
			sys_checksum += *(int *)&x[m + 16 * 0x1000];
367
		}
368
	}
369
 
370
// give some of what we locked back for malloc before returning.  Done
371
// by cheating and passing a negative value to sbrk
372
	working_size -= LOCKED_FOR_MALLOC;
373
	sbrk( -(LOCKED_FOR_MALLOC));
374
	*size = working_size;
375
	return working_memory;
376
}
377
 
378
 
379
/*
380
============
381
Sys_FileTime
382
 
383
returns -1 if not present
384
============
385
*/
386
int	Sys_FileTime (char *path)
387
{
388
	struct	stat	buf;
389
 
390
	if (stat (path,&buf) == -1)
391
		return -1;
392
 
393
	return buf.st_mtime;
394
}
395
 
396
void Sys_mkdir (char *path)
397
{
398
	mkdir (path, 0777);
399
}
400
 
401
 
402
void Sys_Sleep(void)
403
{
404
}
405
 
406
 
407
char *Sys_ConsoleInput(void)
408
{
409
	static char	text[256];
410
	static int	len = 0;
411
	char		ch;
412
 
413
	if (!isDedicated)
414
		return NULL;
415
 
416
	if (! kbhit())
417
		return NULL;
418
 
419
	ch = getche();
420
 
421
	switch (ch)
422
	{
423
		case '\r':
424
			putch('\n');
425
			if (len)
426
			{
427
				text[len] = 0;
428
				len = 0;
429
				return text;
430
			}
431
			break;
432
 
433
		case '\b':
434
			putch(' ');
435
			if (len)
436
			{
437
				len--;
438
				putch('\b');
439
			}
440
			break;
441
 
442
		default:
443
			text[len] = ch;
444
			len = (len + 1) & 0xff;
445
			break;
446
	}
447
 
448
	return NULL;
449
}
450
 
451
void Sys_Init(void)
452
{
453
 
454
	MaskExceptions ();
455
 
456
	Sys_SetFPCW ();
457
 
458
    dos_outportb(0x43, 0x34); // set system timer to mode 2
459
    dos_outportb(0x40, 0);    // for the Sys_FloatTime() function
460
    dos_outportb(0x40, 0);
461
 
462
	Sys_InitFloatTime ();
463
 
464
	_go32_interrupt_stack_size = 4 * 1024;;
465
	_go32_rmcb_stack_size = 4 * 1024;
466
}
467
 
468
void Sys_Shutdown(void)
469
{
470
	if (!isDedicated)
471
		dos_restoreintr(9);
472
 
473
	if (unlockmem)
474
	{
475
		dos_unlockmem (&start_of_memory,
476
					   end_of_memory - (int)&start_of_memory);
477
		dos_unlockmem (quakeparms.membase, quakeparms.memsize);
478
	}
479
}
480
 
481
 
482
#define SC_RSHIFT       0x36
483
#define SC_LSHIFT       0x2a
484
void Sys_SendKeyEvents (void)
485
{
486
	int k, next;
487
	int outkey;
488
 
489
// get key events
490
 
491
	while (keybuf_head != keybuf_tail)
492
	{
493
 
494
		k = keybuf[keybuf_tail++];
495
		keybuf_tail &= (KEYBUF_SIZE-1);
496
 
497
		if (k==0xe0)
498
			continue;               // special / pause keys
499
		next = keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)];
500
		if (next == 0xe1)
501
			continue;                               // pause key bullshit
502
		if (k==0xc5 && next == 0x9d)
503
		{
504
			Key_Event (K_PAUSE, true);
505
			continue;
506
		}
507
 
508
		// extended keyboard shift key bullshit
509
		if ( (k&0x7f)==SC_LSHIFT || (k&0x7f)==SC_RSHIFT )
510
		{
511
			if ( keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)]==0xe0 )
512
				continue;
513
			k &= 0x80;
514
			k |= SC_RSHIFT;
515
		}
516
 
517
		if (k==0xc5 && keybuf[(keybuf_tail-2)&(KEYBUF_SIZE-1)] == 0x9d)
518
			continue; // more pause bullshit
519
 
520
		outkey = scantokey[k & 0x7f];
521
 
522
		if (k & 0x80)
523
			Key_Event (outkey, false);
524
		else
525
			Key_Event (outkey, true);
526
 
527
	}
528
 
529
}
530
 
531
 
532
// =======================================================================
533
// General routines
534
// =======================================================================
535
 
536
/*
537
================
538
Sys_Printf
539
================
540
*/
541
 
542
void Sys_Printf (char *fmt, ...)
543
{
544
	va_list		argptr;
545
	char		text[1024];
546
 
547
	va_start (argptr,fmt);
548
	vsprintf (text,fmt,argptr);
549
	va_end (argptr);
550
 
551
	if (cls.state == ca_dedicated)
552
		fprintf(stderr, "%s", text);
553
}
554
 
555
void Sys_AtExit (void)
556
{
557
 
558
// shutdown only once (so Sys_Error can call this function to shutdown, then
559
// print the error message, then call exit without exit calling this function
560
// again)
561
	Sys_Shutdown();
562
}
563
 
564
 
565
void Sys_Quit (void)
566
{
567
	byte	screen[80*25*2];
568
	byte	*d;
569
	char			ver[6];
570
	int			i;
571
 
572
 
573
// load the sell screen before shuting everything down
574
	if (registered.value)
575
		d = COM_LoadHunkFile ("end2.bin");
576
	else
577
		d = COM_LoadHunkFile ("end1.bin");
578
	if (d)
579
		memcpy (screen, d, sizeof(screen));
580
 
581
// write the version number directly to the end screen
582
	sprintf (ver, " v%4.2f", VERSION);
583
	for (i=0 ; i<6 ; i++)
584
		screen[0*80*2 + 72*2 + i*2] = ver[i];
585
 
586
	Host_Shutdown();
587
 
588
// do the text mode sell screen
589
	if (d)
590
	{
591
		memcpy ((void *)real2ptr(0xb8000), screen,80*25*2);
592
 
593
	// set text pos
594
		regs.x.ax = 0x0200;
595
		regs.h.bh = 0;
596
		regs.h.dl = 0;
597
		regs.h.dh = 22;
598
		dos_int86 (0x10);
599
	}
600
	else
601
		printf ("couldn't load endscreen.\n");
602
 
603
	exit(0);
604
}
605
 
606
void Sys_Error (char *error, ...)
607
{
608
    va_list     argptr;
609
    char        string[1024];
610
 
611
    va_start (argptr,error);
612
    vsprintf (string,error,argptr);
613
    va_end (argptr);
614
 
615
	Host_Shutdown();
616
	fprintf(stderr, "Error: %s\n", string);
617
// Sys_AtExit is called by exit to shutdown the system
618
	exit(0);
619
}
620
 
621
 
622
int Sys_FileOpenRead (char *path, int *handle)
623
{
624
	int	h;
625
	struct stat	fileinfo;
626
 
627
	h = open (path, O_RDONLY|O_BINARY, 0666);
628
	*handle = h;
629
	if (h == -1)
630
		return -1;
631
 
632
	if (fstat (h,&fileinfo) == -1)
633
		Sys_Error ("Error fstating %s", path);
634
 
635
	return fileinfo.st_size;
636
}
637
 
638
int Sys_FileOpenWrite (char *path)
639
{
640
	int     handle;
641
 
642
	umask (0);
643
 
644
	handle = open(path,O_RDWR | O_BINARY | O_CREAT | O_TRUNC
645
	, 0666);
646
 
647
	if (handle == -1)
648
		Sys_Error ("Error opening %s: %s", path,strerror(errno));
649
 
650
	return handle;
651
}
652
 
653
void Sys_FileClose (int handle)
654
{
655
	close (handle);
656
}
657
 
658
void Sys_FileSeek (int handle, int position)
659
{
660
	lseek (handle, position, SEEK_SET);
661
}
662
 
663
int Sys_FileRead (int handle, void *dest, int count)
664
{
665
   return read (handle, dest, count);
666
}
667
 
668
int Sys_FileWrite (int handle, void *data, int count)
669
{
670
	return write (handle, data, count);
671
}
672
 
673
/*
674
================
675
Sys_MakeCodeWriteable
676
================
677
*/
678
void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
679
{
680
	// it's always writeable
681
}
682
 
683
 
684
/*
685
================
686
Sys_FloatTime
687
================
688
*/
689
double Sys_FloatTime (void)
690
{
691
    int				r;
692
    unsigned		t, tick;
693
	double			ft, time;
694
	static int		sametimecount;
695
 
696
	Sys_PushFPCW_SetHigh ();
697
 
698
//{static float t = 0; t=t+0.05; return t;}	// DEBUG
699
 
700
    t = *(unsigned short*)real2ptr(0x46c) * 65536;
701
 
702
    dos_outportb(0x43, 0); // latch time
703
    r = dos_inportb(0x40);
704
    r |= dos_inportb(0x40) << 8;
705
    r = (r-1) & 0xffff;
706
 
707
    tick = *(unsigned short*)real2ptr(0x46c) * 65536;
708
    if ((tick != t) && (r & 0x8000))
709
		t = tick;
710
 
711
	ft = (double) (t+(65536-r)) / 1193200.0;
712
	time = ft - oldtime;
713
	oldtime = ft;
714
 
715
	if (time < 0)
716
	{
717
		if (time > -3000.0)
718
			time = 0.0;
719
		else
720
			time += 3600.0;
721
	}
722
 
723
	curtime += time;
724
 
725
	if (curtime == lastcurtime)
726
	{
727
		sametimecount++;
728
 
729
		if (sametimecount > 100000)
730
		{
731
			curtime += 1.0;
732
			sametimecount = 0;
733
		}
734
	}
735
	else
736
	{
737
		sametimecount = 0;
738
	}
739
 
740
	lastcurtime = curtime;
741
 
742
	Sys_PopFPCW ();
743
 
744
    return curtime;
745
}
746
 
747
 
748
/*
749
================
750
Sys_InitFloatTime
751
================
752
*/
753
void Sys_InitFloatTime (void)
754
{
755
	int		j;
756
 
757
	Sys_FloatTime ();
758
 
759
	oldtime = curtime;
760
 
761
	j = COM_CheckParm("-starttime");
762
 
763
	if (j)
764
	{
765
		curtime = (double) (Q_atof(com_argv[j+1]));
766
	}
767
	else
768
	{
769
		curtime = 0.0;
770
	}
771
	lastcurtime = curtime;
772
}
773
 
774
 
775
/*
776
================
777
Sys_GetMemory
778
================
779
*/
780
void Sys_GetMemory(void)
781
{
782
	int		j, tsize;
783
 
784
	j = COM_CheckParm("-mem");
785
	if (j)
786
	{
787
		quakeparms.memsize = (int) (Q_atof(com_argv[j+1]) * 1024 * 1024);
788
		quakeparms.membase = malloc (quakeparms.memsize);
789
	}
790
	else
791
	{
792
		quakeparms.membase = dos_getmaxlockedmem (&quakeparms.memsize);
793
	}
794
 
795
	fprintf(stderr, "malloc'd: %d\n", quakeparms.memsize);
796
 
797
	if (COM_CheckParm ("-heapsize"))
798
	{
799
		tsize = Q_atoi (com_argv[COM_CheckParm("-heapsize") + 1]) * 1024;
800
 
801
		if (tsize < quakeparms.memsize)
802
			quakeparms.memsize = tsize;
803
	}
804
}
805
 
806
 
807
/*
808
================
809
Sys_PageInProgram
810
 
811
walks the text, data, and bss to make sure it's all paged in so that the
812
actual physical memory detected by Sys_GetMemory is correct.
813
================
814
*/
815
void Sys_PageInProgram(void)
816
{
817
	int		i, j;
818
 
819
	end_of_memory = (int)sbrk(0);
820
 
821
	if (lockmem)
822
	{
823
		if (dos_lockmem ((void *)&start_of_memory,
824
						 end_of_memory - (int)&start_of_memory))
825
			Sys_Error ("Couldn't lock text and data");
826
	}
827
 
828
	if (lockunlockmem)
829
	{
830
		dos_unlockmem((void *)&start_of_memory,
831
						 end_of_memory - (int)&start_of_memory);
832
		printf ("Locked and unlocked %d Mb image\n",
833
				(end_of_memory - (int)&start_of_memory) / 0x100000);
834
	}
835
	else if (lockmem)
836
	{
837
		printf ("Locked %d Mb image\n",
838
				(end_of_memory - (int)&start_of_memory) / 0x100000);
839
	}
840
	else
841
	{
842
		printf ("Loaded %d Mb image\n",
843
				(end_of_memory - (int)&start_of_memory) / 0x100000);
844
	}
845
 
846
// touch the entire image, doing the 16-page skip so Win95 doesn't think we're
847
// trying to page ourselves in
848
	for (j=0 ; j<4 ; j++)
849
	{
850
		for(i=(int)&start_of_memory ; i<(end_of_memory - 16 * 0x1000) ; i += 4)
851
		{
852
			sys_checksum += *(int *)i;
853
			sys_checksum += *(int *)(i + 16 * 0x1000);
854
		}
855
	}
856
}
857
 
858
 
859
/*
860
================
861
Sys_NoFPUExceptionHandler
862
================
863
*/
864
void Sys_NoFPUExceptionHandler(int whatever)
865
{
866
	printf ("\nError: Quake requires a floating-point processor\n");
867
	exit (0);
868
}
869
 
870
 
871
/*
872
================
873
Sys_DefaultExceptionHandler
874
================
875
*/
876
void Sys_DefaultExceptionHandler(int whatever)
877
{
878
}
879
 
880
 
881
/*
882
================
883
main
884
================
885
*/
886
int main (int c, char **v)
887
{
888
	double			time, oldtime, newtime;
889
	extern void (*dos_error_func)(char *, ...);
890
	static	char	cwd[1024];
891
 
892
	printf ("Quake v%4.2f\n", VERSION);
893
 
894
// make sure there's an FPU
895
	signal(SIGNOFP, Sys_NoFPUExceptionHandler);
896
	signal(SIGABRT, Sys_DefaultExceptionHandler);
897
	signal(SIGALRM, Sys_DefaultExceptionHandler);
898
	signal(SIGKILL, Sys_DefaultExceptionHandler);
899
	signal(SIGQUIT, Sys_DefaultExceptionHandler);
900
	signal(SIGINT, Sys_DefaultExceptionHandler);
901
 
902
	if (fptest_temp >= 0.0)
903
		fptest_temp += 0.1;
904
 
905
	COM_InitArgv (c, v);
906
 
907
	quakeparms.argc = com_argc;
908
	quakeparms.argv = com_argv;
909
 
910
	dos_error_func = Sys_Error;
911
 
912
	Sys_DetectWin95 ();
913
	Sys_PageInProgram ();
914
	Sys_GetMemory ();
915
 
916
	atexit (Sys_AtExit);	// in case we crash
917
 
918
	getwd (cwd);
919
	if (cwd[Q_strlen(cwd)-1] == '/') cwd[Q_strlen(cwd)-1] = 0;
920
	quakeparms.basedir = cwd; //"f:/quake";
921
 
922
	isDedicated = (COM_CheckParm ("-dedicated") != 0);
923
 
924
	Sys_Init ();
925
 
926
	if (!isDedicated)
927
		dos_registerintr(9, TrapKey);
928
 
929
//Sys_InitStackCheck ();
930
 
931
	Host_Init(&quakeparms);
932
 
933
//Sys_StackCheck ();
934
 
935
//Con_Printf ("Top of stack: 0x%x\n", &time);
936
	oldtime = Sys_FloatTime ();
937
	while (1)
938
	{
939
		newtime = Sys_FloatTime ();
940
		time = newtime - oldtime;
941
 
942
		if (cls.state == ca_dedicated && (time
943
			continue;
944
 
945
		Host_Frame (time);
946
 
947
//Sys_StackCheck ();
948
 
949
		oldtime = newtime;
950
	}
951
}
952
 
953