home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / pascal / swag / tsr.swg / 0018_TSR Clock.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-01-27  |  3.9 KB  |  180 lines

  1. {
  2. > I would like to include a clock in my current project which will be
  3. > updated once a minute.  Instead of constantly checking the computer's clock
  4. > and waiting for it to change, I would like to use an interrupt.
  5.  
  6. This one has even a hot key handler.  If you want to update it once per
  7. minute, bump a counter within the interrupt 1Ch handler till it reaches the
  8. value 60*18.2.  Then refresh the screen.
  9. }
  10.  
  11. Program Clock;
  12.  
  13. {$G+,R-,S-,M 1024, 0, 0 }
  14.  
  15. uses
  16.   Dos;
  17.  
  18. Const
  19.   x           = 71;                   { x location on screen }
  20.   y           = 1;                    { y location on screen }
  21.   Keyboard    = 9;                    { Hardware keyboard interrupt }
  22.   TimerTick   = $1C;                  { Gets called 18.2 / second }
  23.   VideoOffset = 160 * (y - 1) + 2 * x;{ Offset in display memory }
  24.   yellow      = 14;
  25.   blue        = 1;
  26.   attribute   = blue * 16 + yellow;   { Clock colours }
  27.   VideoBase   : Word = $B800;         { Segment of display memory }
  28.   ActiveFlag  : ShortInt = -1;        { 0: on, -1: off }
  29.  
  30. Var
  31.   OrgInt9,                             { Saved interrupt 9 vector }
  32.   OrgInt1Ch : Pointer;              { Saved interrupt 1Ch vector }
  33.   VideoMode : Byte absolute $0000:$0449;
  34.  
  35. { Display a string using Dos services (avoid WriteLn, save memory) }
  36.  
  37. Procedure DisplayString(s : String); Assembler;
  38.  
  39. ASM
  40.   PUSH   DS
  41.   XOR    CX, CX
  42.   LDS    SI, s
  43.   LODSB
  44.   MOV    CL, AL
  45.   JCXZ   @EmptyString
  46.   CLD
  47.  @NextChar:
  48.   LODSB
  49.   XCHG   AX, DX
  50.   MOV    AH, 2
  51.   INT    21h
  52.   LOOP   @NextChar
  53.  @EmptyString:
  54.   POP    DS
  55. end;
  56.  
  57. { Returns True if a real time clock could be found }
  58. Function HasRTClock : Boolean; Assembler;
  59.  
  60. ASM
  61.   XOR    AL, AL
  62.   MOV    AH, 2
  63.   INT    1Ah
  64.   JC     @NoRTClock
  65.   INC    AX
  66.  @NoRTCLock:
  67. end;
  68.  
  69. { Release Dos environment }
  70. Procedure ReleaseEnvironment; Assembler;
  71. ASM
  72.   MOV    ES, [PrefixSeg]
  73.   MOV    ES, ES:[002Ch]
  74.   MOV    AH, 49h
  75.   INT    21h
  76. end;
  77.  
  78. { INT 9 handler intercepting Alt-F11 }
  79. Procedure ToggleClock; Interrupt; Assembler;
  80. Const
  81.   F11      = $57;                  { 'F11' make code }
  82.   BiosSeg  = $40;                  { Segment of BIOS data area }
  83.   AltMask  = $08;                  { Bitmask of Alt key }
  84.   KbdFlags = $17;                  { Byte showing keyboard status }
  85.  
  86. ASM
  87.   STI
  88.   IN     AL, 60h
  89.  
  90.  { F11 pressed? }
  91.   CMP    AL, F11
  92.   JNE    @PassThru
  93.  
  94.  { Alt-key pressed? }
  95.   PUSH   BiosSeg
  96.   POP    ES
  97.   MOV    AL, ES:[KbdFlags]
  98.   AND    AL, AltMask
  99.   CMP    AL, AltMask
  100.   JNE    @PassThru
  101.  
  102.  { Flip status flag, force EOI and leave routine }
  103.   NOT    [ActiveFlag]
  104.   IN     AL, 61h
  105.   MOV    AH, AL
  106.   OR     AL, 80h
  107.   OUT    61h, AL
  108.   MOV    AL, AH
  109.   OUT    61h, AL
  110.   CLI
  111.   MOV    AL, 20h
  112.   OUT    20h, AL
  113.   STI
  114.   JMP    @Exit
  115.  
  116.  @PassThru:
  117.   CLI
  118.   PUSHF
  119.   CALL   DWord Ptr [OrgInt9]
  120.  @Exit:
  121. end;  { ToggleClock }
  122.  
  123. { Convert a packed BCD byte to ASCII character }
  124. Procedure Digit; Assembler;
  125. ASM
  126.   PUSH   AX
  127.   CALL   @HiNibble
  128.   POP    AX
  129.   CALL   @LoNibble
  130.   RETN
  131.  
  132.  @HiNibble:
  133.   SHR    AL, 4
  134.   JMP    @MakeAscii
  135.  @LoNibble:
  136.   AND    AL, 0Fh
  137.  @MakeAscii:
  138.   OR     AL, '0'
  139.   STOSW
  140. end;
  141.  
  142. { INT 1Ch handler that displays a clock on the right hand side of the screen }
  143. Procedure DisplayClock; Interrupt; Assembler;
  144. ASM
  145.   CMP    [ActiveFlag], 0
  146.   JNE    @Exit
  147.   CLD
  148.   MOV    AH, 2
  149.   INT    1Ah
  150.   MOV    ES, [VideoBase]
  151.   MOV    DI, VideoOffset
  152.   MOV    AH, attribute
  153.   MOV    AL, CH
  154.   CALL   Digit
  155.   MOV    AL, ':'
  156.   STOSW
  157.   MOV    AL, CL
  158.   CALL   Digit
  159.   MOV    AL, ':'
  160.   STOSW
  161.   MOV    AL, DH
  162.   CALL   Digit
  163.   PUSHF
  164.   CALL   DWord Ptr [OrgInt1Ch]
  165.  @Exit:
  166. end;
  167.  
  168. Begin
  169.   If VideoMode = 7 Then
  170.     VideoBase := $B000;
  171.   GetIntVec(TimerTick, OrgInt1Ch);
  172.   SetIntVec(TimerTick, @DisplayClock);
  173.   GetIntVec(Keyboard, OrgInt9);
  174.   SetIntVec(Keyboard, @ToggleClock);
  175.   SwapVectors;
  176.   ReleaseEnvironment;
  177.   DisplayString('CLOCK installed.  <Alt-F11> toggles on/off');
  178.   Keep(0);
  179. end.
  180.