rott/rott/isr.c

843 lines
16 KiB
C
Executable File

/*
Copyright (C) 1994-1995 Apogee Software, Ltd.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
============================================================================
TIMER INTERRUPT
============================================================================
*/
#include <stdlib.h>
#include <stdio.h>
#ifdef DOS
#include <dos.h>
#include <mem.h>
#include <conio.h>
#endif
#include "rt_def.h"
#include "task_man.h"
#include "isr.h"
#include "_isr.h"
#include "rt_in.h"
#include "rt_util.h"
#include "profile.h"
#include "develop.h"
#include "rt_main.h"
#if (DEVELOPMENT == 1)
#include "rt_vid.h"
#endif
//MED
#include "memcheck.h"
// Global Variables
static volatile boolean ExtendedKeyFlag;
volatile int Keyboard[MAXKEYBOARDSCAN];
volatile int KeyboardQueue[KEYQMAX];
volatile int Keystate[MAXKEYBOARDSCAN];
volatile int Keyhead;
volatile int Keytail;
#ifdef DOS
volatile int ticcount;
volatile int fasttics;
#endif
volatile boolean PausePressed = false;
volatile boolean PanicPressed = false;
int KeyboardStarted=false;
const int ASCIINames[] = // Unshifted ASCII for scan codes
{
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0 ,27 ,'1','2','3','4','5','6','7','8','9','0','-','=',8 ,9 , // 0
'q','w','e','r','t','y','u','i','o','p','[',']',13 ,0 ,'a','s', // 1
'd','f','g','h','j','k','l',';',39 ,'`',0 ,92 ,'z','x','c','v', // 2
'b','n','m',',','.','/',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
'2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
};
const int ShiftNames[] = // Shifted ASCII for scan codes
{
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0 ,27 ,'!','@','#','$','%','^','&','*','(',')','_','+',8 ,9 , // 0
'Q','W','E','R','T','Y','U','I','O','P','{','}',13 ,0 ,'A','S', // 1
'D','F','G','H','J','K','L',':',34 ,'~',0 ,'|','Z','X','C','V', // 2
'B','N','M','<','>','?',0 ,'*',0 ,' ',0 ,0 ,0 ,0 ,0 ,0 , // 3
0 ,0 ,0 ,0 ,0 ,0 ,0 ,'7','8','9','-','4','5','6','+','1', // 4
'2','3','0',127,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 5
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , // 6
0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 // 7
};
#ifdef DOS
// Local Variables
static task * timertask;
#if (DEVELOPMENT == 1)
static task * fasttimertask;
#endif
static int TimerStarted=false;
static volatile int pausecount=0;
static struct dostime_t starttime;
void (__interrupt __far *oldtimerisr) ();
void (__interrupt __far *oldkeyboardisr) () = NULL;
static int LEDs;
static volatile int KBFlags;
/*
================
=
= I_TimerISR
=
================
*/
void __interrupt I_TimerISR (void)
{
// acknowledge the interrupt
OUTP(0x20,0x20);
ticcount++;
}
/*
================
=
= ISR_Timer
=
================
*/
#if 0
#if (DEVELOPMENT == 1)
static int time=0;
static int t1=0;
static int t2=0;
static int t3=0;
static int insettime=0;
#endif
#endif
/*
================
=
= ISR_SetTime
=
================
*/
void ISR_SetTime(int settime)
{
#if 0
#if (DEVELOPMENT == 1)
int i;
int t;
int savetime;
#endif
#endif
ticcount=settime;
#if 0
#if (DEVELOPMENT == 1)
{
insettime=1;
savetime=time;
t1=0;
t2=0;
t3=0;
t=0;
for (i=0;i<settime;i++)
{
t++;
if (t==VBLCOUNTER)
{
t=0;
t1++;
if (t1==2)
{
t1=0;
t2++;
if (t2==2)
{
t2=0;
t3++;
if (t3==2)
t3=0;
}
}
}
}
time=t+(time-savetime);
if (time>=VBLCOUNTER)
{
time-=VBLCOUNTER;
t1++;
if (t1==2)
{
t1=0;
t2++;
if (t2==2)
{
t2=0;
t3++;
if (t3==2)
t3=0;
}
}
}
insettime=0;
}
#endif
#endif
}
static void ISR_Timer (task *Task)
{
// (*(int *)(Task->data))=((*(int *)(Task->data))+1)&0xffff;
(*(int *)(Task->data))++;
#if 0
#if (DEVELOPMENT == 1)
{
if (Task==timertask)
{
time++;
if ((time==VBLCOUNTER) && (insettime==0))
{
time=0;
VL_SetColor(0,(t1<<5)+20,(t2<<5)+20,(t3<<5)+20);
t1++;
if (t1==2)
{
t1=0;
t2++;
if (t2==2)
{
t2=0;
t3++;
if (t3==2)
t3=0;
}
}
}
}
}
#endif
#endif
}
/*
=====================
=
= I_SetTimer0
=
= Sets system timer 0 to the specified speed
=
=====================
*/
void I_SetTimer0(int speed)
{
unsigned s;
if (!((speed > 0 && speed < 150)))
Error ("INT_SetTimer0: %i is a bad value",speed);
s=1192030U/(unsigned)speed;
OUTP(0x43,0x36); // Change timer 0
OUTP(0x40,s);
OUTP(0x40,s >> 8);
}
/*
================
=
= I_Delay
=
================
*/
void I_Delay ( int delay )
{
int time;
delay=(VBLCOUNTER*delay)/10;
IN_ClearKeysDown();
time=ticcount;
while (ticcount<time+delay)
{
if (LastScan)
break;
}
}
/*
===============
=
= I_StartupTimer
=
===============
*/
void I_StartupTimer (void)
{
#if PROFILE
return;
#else
struct dostime_t cmostime;
if (TimerStarted==true)
return;
TimerStarted=true;
I_GetCMOSTime ( &cmostime );
_dos_settime ( &cmostime );
// I_SetTimer0(VBLCOUNTER);
// oldtimerisr = _dos_getvect(TIMERINT);
// _dos_setvect (TIMERINT, I_TimerISR);
timertask=TS_ScheduleTask( &ISR_Timer, VBLCOUNTER, 10, &ticcount);
#if (DEVELOPMENT == 1)
fasttimertask=TS_ScheduleTask( &ISR_Timer, VBLCOUNTER*4, 10, &fasttics);
#endif
TS_Dispatch();
I_GetCMOSTime ( &cmostime );
memcpy(&starttime,&cmostime,sizeof(starttime));
ticcount=0;
if (!quiet)
printf("I_StartupTimer: Timer Started\n");
#endif
}
void I_ShutdownTimer (void)
{
#if PROFILE
return;
#else
struct dostime_t dostime;
struct dostime_t cmostime;
#if (DEVELOPMENT == 1)
int totaltime;
#endif
if (TimerStarted==false)
return;
TimerStarted=false;
// OUTP(0x43,0x36); // Change timer 0
// OUTP(0x40,0);
// OUTP(0x40,0);
// _dos_setvect (TIMERINT, oldtimerisr);
I_GetCMOSTime ( &cmostime );
_dos_gettime ( &dostime );
#if (DEVELOPMENT == 1)
SoftError("Time difference in seconds (DOS-CMOS) %ld\n",dostime.second-cmostime.second);
SoftError("Time difference in minutes (DOS-CMOS) %ld\n",dostime.minute-cmostime.minute);
SoftError("Time difference in hour (DOS-CMOS) %ld\n",dostime.hour-cmostime.hour);
totaltime=( ((cmostime.hour-starttime.hour)*3600) +
((cmostime.minute-starttime.minute)*60) +
(cmostime.second-starttime.second)
);
SoftError("Total seconds = %ld Total Tics = %ld Game Tics = %ld\n",totaltime,totaltime*VBLCOUNTER,ticcount);
#endif
TS_Terminate( timertask );
#if (DEVELOPMENT == 1)
TS_Terminate( fasttimertask );
#endif
TS_Shutdown();
// TS_Halt();
/*
if (oldtimerisr)
{
OUTP(0x43,0x36); // Change timer 0
OUTP(0x40,0);
OUTP(0x40,0);
_dos_setvect (TIMERINT, oldtimerisr);
// Set Date and Time from CMOS
OUTP(0x70,0);
time.second=inp(0x71);
OUTP(0x70,2);
time.minute=inp(0x71);
OUTP(0x70,4);
time.hour=inp(0x71);
time.second=(time.second&0x0f)+((time.second>>4)*10);
time.minute=(time.minute&0x0f)+((time.minute>>4)*10);
time.hour=(time.hour&0x0f)+((time.hour>>4)*10);
_dos_settime(&time);
OUTP(0x70,7);
date.day=inp(0x71);
OUTP(0x70,8);
date.month=inp(0x71);
OUTP(0x70,9);
date.year=inp(0x71);
date.day=(date.day&0x0f)+((date.day>>4)*10);
date.month=(date.month&0x0f)+((date.month>>4)*10);
date.year=(date.year&0x0f)+((date.year>>4)*10);
_dos_setdate(&date);
// }
*/
#endif
}
/*
===============
=
= I_GetCMOSTime
=
===============
*/
void I_GetCMOSTime ( struct dostime_t * cmostime )
{
OUTP(0x70,0);
cmostime->second=inp(0x71);
OUTP(0x70,2);
cmostime->minute=inp(0x71);
OUTP(0x70,4);
cmostime->hour=inp(0x71);
cmostime->second=(cmostime->second&0x0f)+((cmostime->second>>4)*10);
cmostime->minute=(cmostime->minute&0x0f)+((cmostime->minute>>4)*10);
cmostime->hour=(cmostime->hour&0x0f)+((cmostime->hour>>4)*10);
}
/*
============================================================================
KEYBOARD
============================================================================
*/
#define ena_kbd 0xae
#define caps_state 0x40
#define num_state 0x20
#define scroll_state 0x10
#define kb_resend 0xfe
#define kb_ack 0xfa
#define kb_pr_led 0x40
#define kb_error 0x80
#define kb_fe 0x20
#define kb_fa 0x10
#define porta 0x60
#define kb_status_port 0x64
#define input_buffer_full 0x02
#define led_cmd 0xed
#define kb_enable 0xf4
#define leds_off 0
#define caps_led_on 0x04
#define num_led_on 0x02
#define scroll_led_on 0x01
/*
================
=
= I_SendKeyboardData
=
================
*/
void I_SendKeyboardData
(
int val
)
{
int retry;
volatile int count;
_disable();
KBFlags &= ~( kb_fe | kb_fa );
count = 0xffff;
while( count-- )
{
if ( !( inp( kb_status_port ) & input_buffer_full ) )
{
break;
}
}
outp( porta, val );
_enable();
retry = 3;
while( retry-- )
{
count = 0x1a00;
while( count-- )
{
if ( KBFlags & kb_fe )
{
break;
}
if ( KBFlags & kb_fa )
{
return;
}
}
}
KBFlags |= kb_error;
}
/*
================
=
= I_SetKeyboardLEDs
=
================
*/
void I_SetKeyboardLEDs
(
int which,
boolean val
)
{
int mask;
int count;
_disable();
KBFlags |= kb_pr_led;
switch( which )
{
case scroll_lock :
mask = scroll_led_on;
break;
case num_lock :
mask = num_led_on;
break;
case caps_lock :
mask = caps_led_on;
break;
default :
mask = 0;
break;
}
if ( val )
{
LEDs |= mask;
}
else
{
LEDs &= ~mask;
}
count = 0;
do
{
if ( count > 3 )
{
break;
}
I_SendKeyboardData( led_cmd );
_disable();
I_SendKeyboardData( LEDs );
_disable();
I_SendKeyboardData( kb_enable );
_disable();
count++;
}
while( KBFlags & kb_error );
_enable();
KBFlags &= ~(kb_pr_led|kb_error);
}
/*
================
=
= I_KeyboardISR
=
================
*/
void __interrupt I_KeyboardISR (void)
{
int k;
int temp;
int keyon;
int strippedkey;
// Get the scan code
k = inp( 0x60 );
// Tell the XT keyboard controller to clear the key
temp = inp( 0x61 );
OUTP ( 0x61, temp | 0x80 );
OUTP ( 0x61, temp );
if ( KBFlags & kb_pr_led )
{
if ( k == kb_resend )
{
// Handle resend
KBFlags |= kb_fe;
}
else if (k == kb_ack)
{
// Handle ack
KBFlags |= kb_fa;
}
}
else if ( pausecount )
{
pausecount--;
}
else if ( k == 0xe1 ) // Handle Pause key
{
PausePressed = true;
pausecount = 5;
}
else if ( k == 0x46 ) // Handle Panic key (Scroll Lock)
{
PanicPressed = true;
}
else
{
if ( k == 0xE0 )
{
ExtendedKeyFlag = true;
}
else
{
keyon = k & 0x80;
strippedkey = k & 0x7f;
if ( ExtendedKeyFlag )
{
if ( ( strippedkey == sc_LShift ) ||
( strippedkey == sc_RShift ) )
{
k = sc_None;
}
/*
else
{
if ( strippedkey == sc_Alt )
{
k = sc_RightAlt | keyon;
}
if ( strippedkey == sc_Control )
{
k = sc_RightCtrl | keyon;
}
}
*/
}
if ( k != sc_None )
{
if ( strippedkey == sc_LShift )
{
k = sc_RShift | keyon;
}
if ( !keyon )
{
LastScan = k;
}
if (k & 0x80) // Up event
{
Keystate[k&0x7f]=0;
}
else // Down event
{
Keystate[k]=1;
}
KeyboardQueue[ Keytail ] = k;
Keytail = ( Keytail + 1 )&( KEYQMAX - 1 );
}
ExtendedKeyFlag = false;
}
}
// acknowledge the interrupt
OUTP ( 0x20, 0x20 );
}
/*
===============
=
= I_StartupKeyboard
=
===============
*/
void I_StartupKeyboard (void)
{
if (KeyboardStarted==true)
return;
KeyboardStarted=true;
LEDs = 0;
KBFlags = 0;
ExtendedKeyFlag = false;
oldkeyboardisr = _dos_getvect(KEYBOARDINT);
_dos_setvect (0x8000 | KEYBOARDINT, I_KeyboardISR);
// I_SetKeyboardLEDs( scroll_lock, 0 );
Keyhead = Keytail = 0;
memset(Keystate,0,sizeof(Keystate));
if (!quiet)
printf("I_StartupKeyboard: Keyboard Started\n");
}
void I_ShutdownKeyboard (void)
{
if (KeyboardStarted==false)
return;
KeyboardStarted=false;
// Clear LEDS
// *( (byte *)0x417 ) &= ~0x70;
_dos_setvect (KEYBOARDINT, oldkeyboardisr);
*(short *)0x41c = *(short *)0x41a; // clear bios key buffer
}
#else
#include "SDL.h"
static int ticoffset; /* offset for SDL_GetTicks() */
static int ticbase; /* game-supplied base */
int GetTicCount (void)
{
return ((SDL_GetTicks() - ticoffset) * VBLCOUNTER) / 1000 + ticbase;
}
/*
================
=
= ISR_SetTime
=
================
*/
void ISR_SetTime(int settime)
{
ticoffset = SDL_GetTicks();
ticbase = settime;
}
/* developer-only */
int GetFastTics (void)
{
/* STUB_FUNCTION; */
return 0;
}
void SetFastTics (int settime)
{
/* STUB_FUNCTION; */
}
/*
================
=
= I_Delay
=
================
*/
void I_Delay ( int delay )
{
int time;
delay=(VBLCOUNTER*delay)/10;
IN_ClearKeysDown();
time=GetTicCount();
while (!LastScan && !IN_GetMouseButtons() && GetTicCount()<time+delay)
{
IN_UpdateKeyboard();
}
}
/*
===============
=
= I_StartupTimer
=
===============
*/
void I_StartupTimer (void)
{
}
void I_ShutdownTimer (void)
{
}
/*
===============
=
= I_StartupKeyboard
=
===============
*/
void I_StartupKeyboard (void)
{
}
void I_ShutdownKeyboard (void)
{
}
#endif