1 /*
2 Copyright (C) 1994-1995 Apogee Software, Ltd.
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
21
22
23 /*
24 ============================================================================
25
26 TIMER INTERRUPT
27
28 ============================================================================
29 */
30 #include <stdlib.h>
31 #include <stdio.h>
32
33 #ifdef DOS
34 #include <dos.h>
35 #include <mem.h>
36 #include <conio.h>
37 #endif
38
39 #include "rt_def.h"
40 #include "task_man.h"
41 #include "isr.h"
42 #include "_isr.h"
43 #include "rt_in.h"
44 #include "rt_util.h"
45 #include "profile.h"
46 #include "develop.h"
47 #include "rt_main.h"
48
49 #if (DEVELOPMENT == 1)
50
51 #include "rt_vid.h"
52
53 #endif
54 //MED
55 #include "memcheck.h"
56
57 // Global Variables
58
59 static volatile boolean ExtendedKeyFlag;
60
61 volatile int Keyboard[MAXKEYBOARDSCAN];
62 volatile int KeyboardQueue[KEYQMAX];
63 volatile int Keystate[MAXKEYBOARDSCAN];
64 volatile int Keyhead;
65 volatile int Keytail;
66
67 #ifdef DOS
68 volatile int ticcount;
69 volatile int fasttics;
70 #endif
71
72 volatile boolean PausePressed = false;
73 volatile boolean PanicPressed = false;
74 int KeyboardStarted=false;
75
76 const int ASCIINames[] = // Unshifted ASCII for scan codes
77 {
78 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
79 0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0
80 'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1
81 'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2
82 'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
83 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
84 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
85 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
86 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
87 };
88
89 const int ShiftNames[] = // Shifted ASCII for scan codes
90 {
91 // 0 1 2 3 4 5 6 7 8 9 A B C D E F
92 0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0
93 'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1
94 'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2
95 'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
96 0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
97 '2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
98 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
99 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
100 };
101
102 #ifdef DOS
103
104 // Local Variables
105
106 static task * timertask;
107 #if (DEVELOPMENT == 1)
108 static task * fasttimertask;
109 #endif
110 static int TimerStarted=false;
111 static volatile int pausecount=0;
112 static struct dostime_t starttime;
113
114 void (__interrupt __far *oldtimerisr) ();
115 void (__interrupt __far *oldkeyboardisr) () = NULL;
116
117 static int LEDs;
118 static volatile int KBFlags;
119
120 /*
121 ================
122 =
123 = I_TimerISR
124 =
125 ================
126 */
127
I_TimerISR(void)128 void __interrupt I_TimerISR (void)
129 {
130 // acknowledge the interrupt
131
132 OUTP(0x20,0x20);
133 ticcount++;
134 }
135
136 /*
137 ================
138 =
139 = ISR_Timer
140 =
141 ================
142 */
143 #if 0
144 #if (DEVELOPMENT == 1)
145 static int time=0;
146 static int t1=0;
147 static int t2=0;
148 static int t3=0;
149 static int insettime=0;
150 #endif
151 #endif
152 /*
153 ================
154 =
155 = ISR_SetTime
156 =
157 ================
158 */
ISR_SetTime(int settime)159 void ISR_SetTime(int settime)
160 {
161 #if 0
162 #if (DEVELOPMENT == 1)
163 int i;
164 int t;
165 int savetime;
166 #endif
167 #endif
168
169 ticcount=settime;
170 #if 0
171 #if (DEVELOPMENT == 1)
172 {
173 insettime=1;
174 savetime=time;
175 t1=0;
176 t2=0;
177 t3=0;
178 t=0;
179
180 for (i=0;i<settime;i++)
181 {
182 t++;
183 if (t==VBLCOUNTER)
184 {
185 t=0;
186 t1++;
187 if (t1==2)
188 {
189 t1=0;
190 t2++;
191 if (t2==2)
192 {
193 t2=0;
194 t3++;
195 if (t3==2)
196 t3=0;
197 }
198 }
199 }
200 }
201 time=t+(time-savetime);
202 if (time>=VBLCOUNTER)
203 {
204 time-=VBLCOUNTER;
205 t1++;
206 if (t1==2)
207 {
208 t1=0;
209 t2++;
210 if (t2==2)
211 {
212 t2=0;
213 t3++;
214 if (t3==2)
215 t3=0;
216 }
217 }
218 }
219 insettime=0;
220 }
221 #endif
222 #endif
223 }
224
ISR_Timer(task * Task)225 static void ISR_Timer (task *Task)
226 {
227 // (*(int *)(Task->data))=((*(int *)(Task->data))+1)&0xffff;
228 (*(int *)(Task->data))++;
229
230 #if 0
231 #if (DEVELOPMENT == 1)
232 {
233 if (Task==timertask)
234 {
235 time++;
236 if ((time==VBLCOUNTER) && (insettime==0))
237 {
238 time=0;
239 VL_SetColor(0,(t1<<5)+20,(t2<<5)+20,(t3<<5)+20);
240 t1++;
241 if (t1==2)
242 {
243 t1=0;
244 t2++;
245 if (t2==2)
246 {
247 t2=0;
248 t3++;
249 if (t3==2)
250 t3=0;
251 }
252 }
253 }
254 }
255 }
256 #endif
257 #endif
258 }
259
260
261 /*
262 =====================
263 =
264 = I_SetTimer0
265 =
266 = Sets system timer 0 to the specified speed
267 =
268 =====================
269 */
270
I_SetTimer0(int speed)271 void I_SetTimer0(int speed)
272 {
273 unsigned s;
274 if (!((speed > 0 && speed < 150)))
275 Error ("INT_SetTimer0: %i is a bad value",speed);
276 s=1192030U/(unsigned)speed;
277 OUTP(0x43,0x36); // Change timer 0
278 OUTP(0x40,s);
279 OUTP(0x40,s >> 8);
280 }
281
282 /*
283 ================
284 =
285 = I_Delay
286 =
287 ================
288 */
289
I_Delay(int delay)290 void I_Delay ( int delay )
291 {
292 int time;
293
294 delay=(VBLCOUNTER*delay)/10;
295 IN_ClearKeysDown();
296 time=ticcount;
297 while (ticcount<time+delay)
298 {
299 if (LastScan)
300 break;
301 }
302 }
303
304 /*
305 ===============
306 =
307 = I_StartupTimer
308 =
309 ===============
310 */
311
I_StartupTimer(void)312 void I_StartupTimer (void)
313 {
314 #if PROFILE
315 return;
316 #else
317 struct dostime_t cmostime;
318
319 if (TimerStarted==true)
320 return;
321 TimerStarted=true;
322
323 I_GetCMOSTime ( &cmostime );
324 _dos_settime ( &cmostime );
325
326 // I_SetTimer0(VBLCOUNTER);
327 // oldtimerisr = _dos_getvect(TIMERINT);
328 // _dos_setvect (TIMERINT, I_TimerISR);
329
330 timertask=TS_ScheduleTask( &ISR_Timer, VBLCOUNTER, 10, &ticcount);
331 #if (DEVELOPMENT == 1)
332 fasttimertask=TS_ScheduleTask( &ISR_Timer, VBLCOUNTER*4, 10, &fasttics);
333 #endif
334 TS_Dispatch();
335 I_GetCMOSTime ( &cmostime );
336 memcpy(&starttime,&cmostime,sizeof(starttime));
337 ticcount=0;
338 if (!quiet)
339 printf("I_StartupTimer: Timer Started\n");
340 #endif
341 }
342
I_ShutdownTimer(void)343 void I_ShutdownTimer (void)
344 {
345 #if PROFILE
346 return;
347 #else
348 struct dostime_t dostime;
349 struct dostime_t cmostime;
350 #if (DEVELOPMENT == 1)
351 int totaltime;
352 #endif
353
354 if (TimerStarted==false)
355 return;
356 TimerStarted=false;
357
358 // OUTP(0x43,0x36); // Change timer 0
359 // OUTP(0x40,0);
360 // OUTP(0x40,0);
361 // _dos_setvect (TIMERINT, oldtimerisr);
362
363 I_GetCMOSTime ( &cmostime );
364 _dos_gettime ( &dostime );
365
366 #if (DEVELOPMENT == 1)
367 SoftError("Time difference in seconds (DOS-CMOS) %ld\n",dostime.second-cmostime.second);
368 SoftError("Time difference in minutes (DOS-CMOS) %ld\n",dostime.minute-cmostime.minute);
369 SoftError("Time difference in hour (DOS-CMOS) %ld\n",dostime.hour-cmostime.hour);
370 totaltime=( ((cmostime.hour-starttime.hour)*3600) +
371 ((cmostime.minute-starttime.minute)*60) +
372 (cmostime.second-starttime.second)
373 );
374 SoftError("Total seconds = %ld Total Tics = %ld Game Tics = %ld\n",totaltime,totaltime*VBLCOUNTER,ticcount);
375 #endif
376
377 TS_Terminate( timertask );
378 #if (DEVELOPMENT == 1)
379 TS_Terminate( fasttimertask );
380 #endif
381 TS_Shutdown();
382 // TS_Halt();
383 /*
384 if (oldtimerisr)
385 {
386 OUTP(0x43,0x36); // Change timer 0
387 OUTP(0x40,0);
388 OUTP(0x40,0);
389 _dos_setvect (TIMERINT, oldtimerisr);
390 // Set Date and Time from CMOS
391
392 OUTP(0x70,0);
393 time.second=inp(0x71);
394 OUTP(0x70,2);
395 time.minute=inp(0x71);
396 OUTP(0x70,4);
397 time.hour=inp(0x71);
398 time.second=(time.second&0x0f)+((time.second>>4)*10);
399 time.minute=(time.minute&0x0f)+((time.minute>>4)*10);
400 time.hour=(time.hour&0x0f)+((time.hour>>4)*10);
401 _dos_settime(&time);
402
403 OUTP(0x70,7);
404 date.day=inp(0x71);
405 OUTP(0x70,8);
406 date.month=inp(0x71);
407 OUTP(0x70,9);
408 date.year=inp(0x71);
409 date.day=(date.day&0x0f)+((date.day>>4)*10);
410 date.month=(date.month&0x0f)+((date.month>>4)*10);
411 date.year=(date.year&0x0f)+((date.year>>4)*10);
412 _dos_setdate(&date);
413 // }
414 */
415 #endif
416 }
417
418 /*
419 ===============
420 =
421 = I_GetCMOSTime
422 =
423 ===============
424 */
I_GetCMOSTime(struct dostime_t * cmostime)425 void I_GetCMOSTime ( struct dostime_t * cmostime )
426 {
427 OUTP(0x70,0);
428 cmostime->second=inp(0x71);
429 OUTP(0x70,2);
430 cmostime->minute=inp(0x71);
431 OUTP(0x70,4);
432 cmostime->hour=inp(0x71);
433 cmostime->second=(cmostime->second&0x0f)+((cmostime->second>>4)*10);
434 cmostime->minute=(cmostime->minute&0x0f)+((cmostime->minute>>4)*10);
435 cmostime->hour=(cmostime->hour&0x0f)+((cmostime->hour>>4)*10);
436 }
437
438 /*
439 ============================================================================
440
441 KEYBOARD
442
443 ============================================================================
444 */
445 #define ena_kbd 0xae
446 #define caps_state 0x40
447 #define num_state 0x20
448 #define scroll_state 0x10
449
450 #define kb_resend 0xfe
451 #define kb_ack 0xfa
452 #define kb_pr_led 0x40
453 #define kb_error 0x80
454 #define kb_fe 0x20
455 #define kb_fa 0x10
456
457 #define porta 0x60
458 #define kb_status_port 0x64
459 #define input_buffer_full 0x02
460 #define led_cmd 0xed
461 #define kb_enable 0xf4
462 #define leds_off 0
463 #define caps_led_on 0x04
464 #define num_led_on 0x02
465 #define scroll_led_on 0x01
466
467 /*
468 ================
469 =
470 = I_SendKeyboardData
471 =
472 ================
473 */
474
I_SendKeyboardData(int val)475 void I_SendKeyboardData
476 (
477 int val
478 )
479
480 {
481 int retry;
482 volatile int count;
483
484 _disable();
485
486 KBFlags &= ~( kb_fe | kb_fa );
487
488 count = 0xffff;
489 while( count-- )
490 {
491 if ( !( inp( kb_status_port ) & input_buffer_full ) )
492 {
493 break;
494 }
495 }
496
497 outp( porta, val );
498
499 _enable();
500
501 retry = 3;
502 while( retry-- )
503 {
504 count = 0x1a00;
505 while( count-- )
506 {
507 if ( KBFlags & kb_fe )
508 {
509 break;
510 }
511
512 if ( KBFlags & kb_fa )
513 {
514 return;
515 }
516 }
517 }
518
519 KBFlags |= kb_error;
520 }
521
522 /*
523 ================
524 =
525 = I_SetKeyboardLEDs
526 =
527 ================
528 */
529
I_SetKeyboardLEDs(int which,boolean val)530 void I_SetKeyboardLEDs
531 (
532 int which,
533 boolean val
534 )
535
536 {
537 int mask;
538 int count;
539
540 _disable();
541 KBFlags |= kb_pr_led;
542
543 switch( which )
544 {
545 case scroll_lock :
546 mask = scroll_led_on;
547 break;
548
549 case num_lock :
550 mask = num_led_on;
551 break;
552
553 case caps_lock :
554 mask = caps_led_on;
555 break;
556
557 default :
558 mask = 0;
559 break;
560 }
561
562 if ( val )
563 {
564 LEDs |= mask;
565 }
566 else
567 {
568 LEDs &= ~mask;
569 }
570
571 count = 0;
572 do
573 {
574 if ( count > 3 )
575 {
576 break;
577 }
578
579 I_SendKeyboardData( led_cmd );
580 _disable();
581 I_SendKeyboardData( LEDs );
582 _disable();
583 I_SendKeyboardData( kb_enable );
584 _disable();
585 count++;
586 }
587 while( KBFlags & kb_error );
588
589 _enable();
590 KBFlags &= ~(kb_pr_led|kb_error);
591 }
592
593
594 /*
595 ================
596 =
597 = I_KeyboardISR
598 =
599 ================
600 */
I_KeyboardISR(void)601 void __interrupt I_KeyboardISR (void)
602 {
603 int k;
604 int temp;
605 int keyon;
606 int strippedkey;
607
608 // Get the scan code
609 k = inp( 0x60 );
610
611 // Tell the XT keyboard controller to clear the key
612 temp = inp( 0x61 );
613 OUTP ( 0x61, temp | 0x80 );
614 OUTP ( 0x61, temp );
615
616 if ( KBFlags & kb_pr_led )
617 {
618 if ( k == kb_resend )
619 {
620 // Handle resend
621 KBFlags |= kb_fe;
622 }
623 else if (k == kb_ack)
624 {
625 // Handle ack
626 KBFlags |= kb_fa;
627 }
628 }
629 else if ( pausecount )
630 {
631 pausecount--;
632 }
633 else if ( k == 0xe1 ) // Handle Pause key
634 {
635 PausePressed = true;
636 pausecount = 5;
637 }
638 else if ( k == 0x46 ) // Handle Panic key (Scroll Lock)
639 {
640 PanicPressed = true;
641 }
642 else
643 {
644 if ( k == 0xE0 )
645 {
646 ExtendedKeyFlag = true;
647 }
648 else
649 {
650 keyon = k & 0x80;
651 strippedkey = k & 0x7f;
652
653 if ( ExtendedKeyFlag )
654 {
655 if ( ( strippedkey == sc_LShift ) ||
656 ( strippedkey == sc_RShift ) )
657 {
658 k = sc_None;
659 }
660 /*
661 else
662 {
663 if ( strippedkey == sc_Alt )
664 {
665 k = sc_RightAlt | keyon;
666 }
667 if ( strippedkey == sc_Control )
668 {
669 k = sc_RightCtrl | keyon;
670 }
671 }
672 */
673 }
674
675 if ( k != sc_None )
676 {
677 if ( strippedkey == sc_LShift )
678 {
679 k = sc_RShift | keyon;
680 }
681
682 if ( !keyon )
683 {
684 LastScan = k;
685 }
686
687 if (k & 0x80) // Up event
688 {
689 Keystate[k&0x7f]=0;
690 }
691 else // Down event
692 {
693 Keystate[k]=1;
694 }
695
696 KeyboardQueue[ Keytail ] = k;
697 Keytail = ( Keytail + 1 )&( KEYQMAX - 1 );
698 }
699
700 ExtendedKeyFlag = false;
701 }
702 }
703
704 // acknowledge the interrupt
705 OUTP ( 0x20, 0x20 );
706 }
707
708
709 /*
710 ===============
711 =
712 = I_StartupKeyboard
713 =
714 ===============
715 */
716
I_StartupKeyboard(void)717 void I_StartupKeyboard (void)
718 {
719 if (KeyboardStarted==true)
720 return;
721 KeyboardStarted=true;
722
723 LEDs = 0;
724 KBFlags = 0;
725 ExtendedKeyFlag = false;
726
727 oldkeyboardisr = _dos_getvect(KEYBOARDINT);
728 _dos_setvect (0x8000 | KEYBOARDINT, I_KeyboardISR);
729
730 // I_SetKeyboardLEDs( scroll_lock, 0 );
731
732 Keyhead = Keytail = 0;
733 memset(Keystate,0,sizeof(Keystate));
734 if (!quiet)
735 printf("I_StartupKeyboard: Keyboard Started\n");
736 }
737
I_ShutdownKeyboard(void)738 void I_ShutdownKeyboard (void)
739 {
740 if (KeyboardStarted==false)
741 return;
742 KeyboardStarted=false;
743
744 // Clear LEDS
745 // *( (byte *)0x417 ) &= ~0x70;
746
747 _dos_setvect (KEYBOARDINT, oldkeyboardisr);
748 *(short *)0x41c = *(short *)0x41a; // clear bios key buffer
749 }
750 #else
751
752 #include "SDL.h"
753
754 static int ticoffset; /* offset for SDL_GetTicks() */
755 static int ticbase; /* game-supplied base */
756
GetTicCount(void)757 int GetTicCount (void)
758 {
759 return ((SDL_GetTicks() - ticoffset) * VBLCOUNTER) / 1000 + ticbase;
760 }
761
762 /*
763 ================
764 =
765 = ISR_SetTime
766 =
767 ================
768 */
ISR_SetTime(int settime)769 void ISR_SetTime(int settime)
770 {
771 ticoffset = SDL_GetTicks();
772 ticbase = settime;
773 }
774
775 /* developer-only */
776
GetFastTics(void)777 int GetFastTics (void)
778 {
779 /* STUB_FUNCTION; */
780
781 return 0;
782 }
783
SetFastTics(int settime)784 void SetFastTics (int settime)
785 {
786 /* STUB_FUNCTION; */
787 }
788
789 /*
790 ================
791 =
792 = I_Delay
793 =
794 ================
795 */
796
I_Delay(int delay)797 void I_Delay ( int delay )
798 {
799 int time;
800
801 delay=(VBLCOUNTER*delay)/10;
802 IN_ClearKeysDown();
803 time=GetTicCount();
804 while (GetTicCount()<time+delay)
805 {
806 if (LastScan)
807 break;
808 }
809 }
810
811 /*
812 ===============
813 =
814 = I_StartupTimer
815 =
816 ===============
817 */
818
I_StartupTimer(void)819 void I_StartupTimer (void)
820 {
821 }
822
I_ShutdownTimer(void)823 void I_ShutdownTimer (void)
824 {
825 }
826
827 /*
828 ===============
829 =
830 = I_StartupKeyboard
831 =
832 ===============
833 */
834
I_StartupKeyboard(void)835 void I_StartupKeyboard (void)
836 {
837 }
838
839
I_ShutdownKeyboard(void)840 void I_ShutdownKeyboard (void)
841 {
842 }
843 #endif
844