shithub: rott

ref: 88e27aeb0d9f472c0bb36a13e503e60dc9d9ec67
dir: /rott/isr.c/

View raw version
/*
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