home *** CD-ROM | disk | FTP | other *** search
- {----------------------------------------------------------------------}
- { }
- { TIMER.INC - simple timer interrupt routine }
- { increments a counter 18.2 times a second }
- { }
- { This code is intended to be included within a larger program. }
- { The main program must first call Timer_Init to initialize the }
- { interrupt vector. Before terminating, Timer_Close must be called }
- { to restore the interrupt vector contents. }
- { Timer_Counter contains the elapsed time and canbe interrogated and }
- { reset by the main routine. }
- { }
- { This code is heavily dependant on the characteristics of the IBM PC }
- { and PC DOS release 2.0. }
- { }
- { Michael Quinlan }
- { }
- {----------------------------------------------------------------------}
-
- { CONST areas are used because on entry, the interrupt service routine
- only has the correct Code Segment; the Data Segment register value must
- be obtained from the Code Segment }
-
- const
- Timer_DSeg_Save : Integer = 0; { save DS register in Code segment for ISR }
-
- const
- Timer_Vector = $1C; { Interrupt vector for timer routine }
-
- const
- Timer_Old_Int : record { area to save the old interrupt vector value }
- o, s : integer
- end = (o:0; s:0); { must be in CODE segment for ISR }
-
- var
- Timer_Counter : Integer; { counter incremented 18.2 times a second }
-
- var
- DOS_Regs : Record
- ax, bx, cx, dx, bp, si, di, ds, es, flag : integer
- end;
-
- procedure DOS_Set_Intrpt(v, s, o : integer);
- { call PC DOS to set an interrupt vector }
- begin
- with DOS_Regs do
- begin
- ax := $2500 + (v and $00FF);
- ds := s;
- dx := o;
- MsDos(DOS_Regs)
- end
- end; { DOS_Set_Intrpt }
-
- procedure DOS_Get_Intrpt(v : integer; var s, o : integer);
- { call PC DOS to get the value of an interrupt vector }
- begin
- with DOS_Regs do
- begin
- ax := $3500 + (v and $00FF);
- MsDos(Dos_Regs);
- s := es;
- o := bx
- end
- end; { DOS_Get_Intrpt }
-
- {----------------------------------------------------------------------}
- { }
- { TIMERISR -- PCDOS Timer Interrupt. Increments a counter 18.2 times }
- { a second. }
- { }
- {----------------------------------------------------------------------}
-
- procedure Timer_Isr;
- begin
-
- { on entry, Turbo Pascal has saved BP and SP on the stack }
- { the manual is incorrect }
-
- Inline(
- { save all registers used }
- $50/ { PUSH AX }
- $1E/ { PUSH DS }
- { set up the DS register to point to the data segment }
- $2E/$FF/$36/Timer_DSeg_Save/ { PUSH CS:Timer_DSeg_Save }
- $1F/ { POP DS }
- $FA/ { CLI }
- $A1/Timer_Counter/ { MOV AX,Timer_Counter }
- $3D/MaxInt/ { CMP AX,MaxInt }
- $74/$04/ { JE L001 }
- $FF/$06/Timer_Counter/ { INC Timer_Counter }
- {L001:}
- $FB/ { STI }
- { invoke any other timer routines installed }
- { it will be her responsibility to issue the IRET }
- { restore the registers first }
- $1F/ { POP DS }
- $58/ { POP AX }
- $5C/ { POP SP }
- $5D/ { POP BP }
- $2E/$FF/$2E/Timer_Old_Int) { JMP CS:Timer_Old_Int (cross-segment,
- indirect) }
- end; { Timer_Isr }
-
- procedure Timer_Init;
- { install the timer interrupt }
- begin
- Timer_DSeg_Save := DSeg; { save DS register for ISR }
- { get the current contents of the timer interrupt vector }
- { the TIMER ISR will invoke this to finish any timer processing }
- DOS_Get_Intrpt(Timer_Vector, Timer_Old_Int.s, Timer_Old_Int.o);
- { begin executing the timer interrupt }
- DOS_Set_Intrpt(Timer_Vector, CSeg, Ofs(Timer_Isr))
- end; { Timer_Init }
-
- procedure Timer_Close;
- { remove the timer interrupt }
- begin
- DOS_Set_Intrpt(Timer_Vector, Timer_Old_Int.s, Timer_Old_Int.o)
- end; { Timer_Close }
- d