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 |