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